react-native-audio-browser 0.2.0-next.3 → 0.2.0-next.31
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 +36 -22
- package/android/build.gradle +35 -12
- package/android/gradle.properties +2 -2
- package/android/src/main/AndroidManifest.xml +3 -1
- package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +541 -278
- package/android/src/main/java/com/audiobrowser/AudioBrowserLifecycleModule.kt +38 -0
- package/android/src/main/java/com/audiobrowser/AudioBrowserPackage.kt +18 -2
- package/android/src/main/java/com/audiobrowser/ServiceBinding.kt +52 -0
- package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +315 -213
- package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +27 -9
- package/android/src/main/java/com/audiobrowser/browser/InertStyleDiagnostic.kt +288 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +97 -58
- package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +70 -29
- package/android/src/main/java/com/audiobrowser/browser/StyleResolver.kt +60 -0
- package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +20 -7
- package/android/src/main/java/com/audiobrowser/extension/TappedTrack.kt +20 -0
- package/android/src/main/java/com/audiobrowser/extension/TrackIdentity.kt +15 -0
- package/android/src/main/java/com/audiobrowser/http/HttpClient.kt +20 -3
- package/android/src/main/java/com/audiobrowser/model/IcyTitle.kt +24 -0
- package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +10 -6
- package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +12 -12
- package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +111 -58
- package/android/src/main/java/com/audiobrowser/player/CrossOriginHeaderStripper.kt +77 -0
- package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +28 -10
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +509 -230
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +218 -252
- package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +21 -25
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +113 -78
- package/android/src/main/java/com/audiobrowser/player/Player.kt +81 -38
- package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +2 -15
- package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +1 -1
- package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +2 -1
- package/android/src/main/java/com/audiobrowser/player/ShuffleOrderLedBy.kt +30 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +67 -11
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingExtendedTrustManager.kt +168 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +58 -14
- package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +35 -7
- package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +278 -59
- package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +7 -9
- package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +62 -40
- package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +28 -23
- package/android/src/main/java/com/audiobrowser/util/StyleWire.kt +110 -0
- package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +56 -52
- package/android/src/main/res/values/strings.xml +25 -5
- package/android/src/test/java/com/audiobrowser/ServiceBindingTest.kt +100 -0
- package/android/src/test/java/com/audiobrowser/TestFixtures.kt +119 -33
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerFavoritesTest.kt +153 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +15 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +346 -8
- package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +40 -2
- package/android/src/test/java/com/audiobrowser/browser/InertStyleDiagnosticTest.kt +301 -0
- package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +3 -2
- package/android/src/test/java/com/audiobrowser/browser/JsonStyleTest.kt +168 -0
- package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +128 -55
- package/android/src/test/java/com/audiobrowser/browser/StyleResolverTest.kt +160 -0
- package/android/src/test/java/com/audiobrowser/extension/TappedTrackTest.kt +43 -0
- package/android/src/test/java/com/audiobrowser/extension/TrackIdentityTest.kt +41 -0
- package/android/src/test/java/com/audiobrowser/model/IcyTitleTest.kt +49 -0
- package/android/src/test/java/com/audiobrowser/player/BrowseTilesTest.kt +385 -0
- package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +101 -58
- package/android/src/test/java/com/audiobrowser/player/CrossOriginHeaderStripperTest.kt +94 -0
- package/android/src/test/java/com/audiobrowser/player/MediaSessionSlotMappingTest.kt +45 -0
- package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +42 -2
- package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +3 -4
- package/android/src/test/java/com/audiobrowser/player/PlaybackStateStoreTrackJsonTest.kt +55 -0
- package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +3 -3
- package/android/src/test/java/com/audiobrowser/player/ShuffleOrderLedByTest.kt +79 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +197 -7
- package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +325 -4
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherCallSiteTest.kt +322 -0
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +83 -0
- package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +55 -16
- package/android/src/test/java/com/audiobrowser/util/MediaExtrasBuilderTest.kt +162 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +7 -7
- package/ios/AVPlayerEngine.swift +330 -0
- package/ios/AVPlayerEngineCallbacks.swift +15 -0
- package/ios/Browser/BrowseGate.swift +58 -0
- package/ios/Browser/BrowserConfig.swift +117 -78
- package/ios/Browser/BrowserManager.swift +209 -603
- package/ios/Browser/BrowserPathHelper.swift +50 -46
- package/ios/Browser/InertStyleDiagnostic.swift +296 -0
- package/ios/Browser/JsonModels.swift +264 -106
- package/ios/Browser/NavigationErrorState.swift +41 -0
- package/ios/Browser/PageResolver.swift +227 -0
- package/ios/Browser/RequestLayer.swift +90 -0
- package/ios/Browser/{BrowserManager+URLResolution.swift → RequestPipeline.swift} +193 -121
- package/ios/Browser/SearchDrillIn.swift +7 -7
- 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/CPInterfaceController+Safe.swift +100 -43
- package/ios/CarPlay/CarPlayArtworkResolver.swift +36 -83
- package/ios/CarPlay/CarPlayController.swift +42 -1296
- package/ios/CarPlay/CarPlayImageLoader.swift +78 -97
- package/ios/CarPlay/CarPlayListItemFactory.swift +303 -92
- package/ios/CarPlay/CarPlayNowPlayingManager.swift +129 -136
- package/ios/CarPlay/CarPlaySession+Navigator.swift +114 -0
- package/ios/CarPlay/CarPlaySession+PageLoader.swift +92 -0
- package/ios/CarPlay/CarPlaySession+Refresher.swift +43 -0
- package/ios/CarPlay/CarPlaySession+TabBar.swift +193 -0
- package/ios/CarPlay/CarPlaySession.swift +209 -0
- package/ios/CarPlay/CarPlayTemplates.swift +63 -0
- package/ios/CarPlay/HybridAudioBrowser+IntentFavorite.swift +20 -0
- package/ios/{Player → CarPlay}/MediaIntentCriteria.swift +17 -9
- package/ios/CarPlay/MediaIntentPlayback.swift +74 -0
- package/ios/CarPlay/RNABMediaAddHandler.swift +8 -24
- package/ios/CarPlay/RNABMediaAffinityHandler.swift +7 -23
- package/ios/CarPlay/RNABMediaIntentHandler.swift +18 -19
- package/ios/CarPlay/SectionPresentation.swift +77 -0
- package/ios/CarPlay/TopTemplateReplacer.swift +96 -0
- package/ios/Extension/Capability+RemoteCommand.swift +1 -1
- package/ios/Extension/NavigationError+Conversion.swift +14 -4
- package/ios/Extension/PlayerCapabilities+Favorite.swift +1 -15
- package/ios/Extension/ResolvedTrack+Copying.swift +13 -15
- package/ios/Extension/Section+Copying.swift +29 -0
- package/ios/Extension/String+IcyCharset.swift +21 -0
- package/ios/Extension/TimedMetadata+AVFoundation.swift +6 -4
- package/ios/Extension/Track+Copying.swift +8 -12
- package/ios/Extension/Track+Identity.swift +18 -0
- package/ios/Extension/UIApplication+ActiveScene.swift +27 -0
- package/ios/Extension/UIImage+Adaptive.swift +12 -0
- package/ios/Extension/URLError+Connectivity.swift +15 -0
- package/ios/Http/HttpClient.swift +66 -142
- package/ios/HybridAudioBrowser+Browser.swift +153 -0
- package/ios/HybridAudioBrowser+Options.swift +144 -0
- package/ios/HybridAudioBrowser+Player.swift +397 -0
- package/ios/HybridAudioBrowser+PlayerCallbacks.swift +189 -0
- package/ios/HybridAudioBrowser+Stubs.swift +46 -0
- package/ios/HybridAudioBrowser.swift +153 -1610
- package/ios/Model/NitroTypeStubs.swift +146 -24
- package/ios/Model/PlayerUpdateOptions.swift +8 -1
- package/ios/Model/RemoteCommand.swift +18 -0
- package/ios/Model/TrackPlayerError.swift +2 -2
- package/ios/NowPlayingInfo/NowPlayingInfoController.swift +18 -53
- package/ios/Observer/ItemObserver.swift +90 -0
- package/ios/Observer/PlayerObserver.swift +59 -0
- package/ios/Option/SessionCategories.swift +42 -92
- package/ios/Player/AudioSessionController.swift +189 -0
- package/ios/Player/DeferredSeek.swift +70 -0
- package/ios/Player/ErrorStatus.swift +27 -0
- package/ios/Player/MediaLoader.swift +62 -35
- package/ios/Player/NowPlayingUpdater.swift +197 -50
- package/ios/Player/PlaybackFailure.swift +125 -0
- package/ios/Player/PlaybackPersistence.swift +73 -0
- package/ios/Player/PlaybackTimer.swift +8 -2
- package/ios/Player/Player.swift +1078 -0
- package/ios/Player/{PlaybackCoordinatorCallbacks.swift → PlayerCallbacks.swift} +3 -4
- package/ios/Player/PlayerEngine.swift +87 -0
- package/ios/Player/PlayerStatusTypes.swift +2 -6
- package/ios/Player/QueueManager.swift +93 -67
- package/ios/Player/RetryLoop.swift +261 -0
- package/ios/Player/ShuffleOrder.swift +33 -0
- package/ios/Player/SleepTimerManager.swift +1 -1
- package/ios/RemoteCommand/RemoteCommandCallbacks.swift +46 -0
- package/ios/RemoteCommand/RemoteCommandController.swift +87 -331
- package/ios/Tests/BrowserPathHelperTests.swift +56 -15
- package/ios/Tests/CarPlayArtworkResolverTests.swift +60 -373
- package/ios/Tests/DeferredSeekTests.swift +70 -0
- package/ios/Tests/EmitterTests.swift +29 -0
- package/ios/Tests/GenerationMemoTests.swift +121 -0
- package/ios/Tests/InertStyleDiagnosticTests.swift +209 -0
- package/ios/Tests/JsonModelsTests.swift +164 -1
- package/ios/Tests/LRUCacheTests.swift +110 -0
- package/ios/Tests/MediaIntentCriteriaTests.swift +2 -2
- package/ios/Tests/MediaLoaderTests.swift +12 -48
- package/ios/Tests/ObserverTests.swift +88 -0
- package/ios/Tests/PlaybackErrorTests.swift +76 -0
- package/ios/Tests/PlaybackFailureTests.swift +189 -0
- package/ios/Tests/PlaybackPersistenceTests.swift +93 -0
- package/ios/Tests/PlayerPolicyTests.swift +420 -0
- package/ios/Tests/{PlaybackCoordinatorTests.swift → PlayerTests.swift} +300 -248
- package/ios/Tests/PlayingStateTests.swift +42 -0
- package/ios/Tests/QueueManagerTests.swift +196 -115
- package/ios/Tests/ReadyValueTests.swift +73 -0
- package/ios/Tests/RemoteCommandControllerTests.swift +152 -0
- package/ios/Tests/RemoteCommandTests.swift +65 -0
- package/ios/Tests/RequestLayerTests.swift +112 -0
- package/ios/Tests/ResolvedTrackCopyingTests.swift +39 -35
- package/ios/Tests/RetryLoopTests.swift +270 -0
- package/ios/Tests/SearchDrillInTests.swift +16 -16
- package/ios/Tests/SectionPresentationTests.swift +98 -0
- package/ios/Tests/SectionScopeTests.swift +87 -55
- package/ios/Tests/StyleResolverTests.swift +132 -0
- package/ios/Tests/Support/TestTypes.swift +108 -104
- package/ios/Tests/TabBarEntriesTests.swift +19 -19
- package/ios/Tests/TimedMetadataAVFoundationTests.swift +42 -0
- package/ios/Tests/TopTemplateReplacerTests.swift +172 -0
- package/ios/Tests/TrackIdTemplateTests.swift +67 -0
- package/ios/Tests/TrackIdentityTests.swift +20 -0
- package/ios/Tests/TrackSelectorTests.swift +168 -33
- package/ios/Tests/URLErrorConnectivityTests.swift +20 -0
- package/ios/TrackSelector.swift +46 -31
- package/ios/Util/ArtworkImageFetcher.swift +58 -1
- package/ios/Util/Emitter.swift +42 -0
- package/ios/Util/GenerationMemo.swift +36 -0
- package/ios/Util/LRUCache.swift +23 -159
- package/ios/Util/NetworkMonitor.swift +43 -26
- package/ios/Util/ReadyValue.swift +56 -0
- package/ios/Util/SFSymbolRenderer.swift +59 -31
- package/ios/Util/SVGProcessor.swift +9 -12
- package/lib/commonjs/AudioBrowser.js +8 -8
- package/lib/commonjs/AudioBrowser.js.map +1 -1
- package/lib/commonjs/CLAUDE.md +52 -0
- package/lib/commonjs/features/browser-config.js +12 -8
- package/lib/commonjs/features/browser-config.js.map +1 -1
- package/lib/commonjs/features/browser.js +11 -3
- package/lib/commonjs/features/browser.js.map +1 -1
- package/lib/commonjs/features/carConnection.js +1 -1
- package/lib/commonjs/features/equalizer.js +1 -1
- package/lib/commonjs/features/errors.js +3 -3
- package/lib/commonjs/features/favorites.js +14 -11
- package/lib/commonjs/features/favorites.js.map +1 -1
- package/lib/commonjs/features/gate.js +16 -1
- package/lib/commonjs/features/gate.js.map +1 -1
- package/lib/commonjs/features/metadata.js +20 -3
- package/lib/commonjs/features/metadata.js.map +1 -1
- package/lib/commonjs/features/network.js +1 -1
- package/lib/commonjs/features/nowPlaying.js +1 -1
- package/lib/commonjs/features/output.js +1 -1
- package/lib/commonjs/features/playback/controls.js +4 -2
- package/lib/commonjs/features/playback/controls.js.map +1 -1
- package/lib/commonjs/features/playback/playWhenReady.js +1 -1
- package/lib/commonjs/features/playback/playing.js +1 -1
- package/lib/commonjs/features/playback/progress.js +3 -2
- package/lib/commonjs/features/playback/progress.js.map +1 -1
- package/lib/commonjs/features/playback/rate.js +8 -1
- package/lib/commonjs/features/playback/rate.js.map +1 -1
- package/lib/commonjs/features/playback/state.js +3 -4
- package/lib/commonjs/features/playback/state.js.map +1 -1
- package/lib/commonjs/features/playback/trackPlaybackTime.js +0 -6
- package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -1
- package/lib/commonjs/features/playback/volume.js +1 -1
- package/lib/commonjs/features/player/options.js +48 -34
- package/lib/commonjs/features/player/options.js.map +1 -1
- package/lib/commonjs/features/player/setup.js +18 -9
- package/lib/commonjs/features/player/setup.js.map +1 -1
- package/lib/commonjs/features/player/validateOptions.js +23 -0
- package/lib/commonjs/features/player/validateOptions.js.map +1 -0
- package/lib/commonjs/features/queue/activeTrack.js +15 -4
- package/lib/commonjs/features/queue/activeTrack.js.map +1 -1
- package/lib/commonjs/features/queue/queue.js +13 -6
- package/lib/commonjs/features/queue/queue.js.map +1 -1
- package/lib/commonjs/features/queue/repeatMode.js +1 -1
- package/lib/commonjs/features/queue/shuffle.js +1 -1
- package/lib/commonjs/features/remoteControls.js +13 -92
- package/lib/commonjs/features/remoteControls.js.map +1 -1
- package/lib/commonjs/features/sleepTimer.js +13 -1
- package/lib/commonjs/features/sleepTimer.js.map +1 -1
- package/lib/commonjs/test-utils/reactNativeStub.js +65 -0
- package/lib/commonjs/test-utils/reactNativeStub.js.map +1 -0
- package/lib/commonjs/utils/LazyNativeEmitter.js +28 -14
- package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/commonjs/utils/NativeUpdatedValue.js +31 -13
- package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/commonjs/utils/getTrackIdentity.js +24 -0
- package/lib/commonjs/utils/getTrackIdentity.js.map +1 -0
- package/lib/commonjs/utils/useNativeValueRefreshedBy.js +33 -0
- package/lib/commonjs/utils/useNativeValueRefreshedBy.js.map +1 -0
- package/lib/commonjs/web/NativeAudioBrowser.js +201 -76
- package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/LoadAttempt.js +37 -0
- package/lib/commonjs/web/TrackPlayer/LoadAttempt.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +18 -2
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/Player.js +254 -39
- package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +1 -1
- package/lib/commonjs/web/TrackPlayer/QueueManager.js +14 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +33 -12
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -1
- package/lib/commonjs/web/browser/BrowserManager.js +175 -100
- package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
- package/lib/commonjs/web/browser/FavoriteManager.js +30 -21
- package/lib/commonjs/web/browser/FavoriteManager.js.map +1 -1
- package/lib/commonjs/web/browser/NavigationErrorManager.js +3 -1
- package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -1
- package/lib/commonjs/web/browser/SearchManager.js +18 -23
- package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
- package/lib/commonjs/web/browser/assertBrowsePageShape.js +2 -2
- package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -1
- package/lib/commonjs/web/browser/classifyTrackNavigation.js +9 -9
- package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -1
- package/lib/commonjs/web/browser/sections.js +89 -0
- package/lib/commonjs/web/browser/sections.js.map +1 -0
- package/lib/commonjs/web/http/RequestConfigBuilder.js +110 -27
- package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/commonjs/web/http/followMediaRedirect.js +219 -0
- package/lib/commonjs/web/http/followMediaRedirect.js.map +1 -0
- package/lib/commonjs/web/player/NowPlayingManager.js +4 -3
- package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
- package/lib/commonjs/web/util/BrowserPathHelper.js +62 -11
- package/lib/commonjs/web/util/BrowserPathHelper.js.map +1 -1
- package/lib/module/AudioBrowser.js +2 -1
- package/lib/module/AudioBrowser.js.map +1 -1
- package/lib/module/CLAUDE.md +52 -0
- package/lib/module/features/browser-config.js +12 -8
- package/lib/module/features/browser-config.js.map +1 -1
- package/lib/module/features/browser.js +11 -3
- package/lib/module/features/browser.js.map +1 -1
- package/lib/module/features/carConnection.js +1 -1
- package/lib/module/features/equalizer.js +1 -1
- package/lib/module/features/errors.js +3 -3
- package/lib/module/features/favorites.js +14 -11
- package/lib/module/features/favorites.js.map +1 -1
- package/lib/module/features/gate.js +16 -1
- package/lib/module/features/gate.js.map +1 -1
- package/lib/module/features/metadata.js +20 -3
- package/lib/module/features/metadata.js.map +1 -1
- package/lib/module/features/network.js +1 -1
- package/lib/module/features/nowPlaying.js +1 -1
- package/lib/module/features/output.js +1 -1
- package/lib/module/features/playback/controls.js +4 -2
- package/lib/module/features/playback/controls.js.map +1 -1
- package/lib/module/features/playback/playWhenReady.js +1 -1
- package/lib/module/features/playback/playing.js +1 -1
- package/lib/module/features/playback/progress.js +3 -2
- package/lib/module/features/playback/progress.js.map +1 -1
- package/lib/module/features/playback/rate.js +8 -1
- package/lib/module/features/playback/rate.js.map +1 -1
- package/lib/module/features/playback/state.js +3 -4
- package/lib/module/features/playback/state.js.map +1 -1
- package/lib/module/features/playback/trackPlaybackTime.js +0 -5
- package/lib/module/features/playback/trackPlaybackTime.js.map +1 -1
- package/lib/module/features/playback/volume.js +1 -1
- package/lib/module/features/player/options.js +47 -32
- package/lib/module/features/player/options.js.map +1 -1
- package/lib/module/features/player/setup.js +17 -8
- package/lib/module/features/player/setup.js.map +1 -1
- package/lib/module/features/player/validateOptions.js +19 -0
- package/lib/module/features/player/validateOptions.js.map +1 -0
- package/lib/module/features/queue/activeTrack.js +15 -4
- package/lib/module/features/queue/activeTrack.js.map +1 -1
- package/lib/module/features/queue/queue.js +13 -6
- package/lib/module/features/queue/queue.js.map +1 -1
- package/lib/module/features/queue/repeatMode.js +1 -1
- package/lib/module/features/queue/shuffle.js +1 -1
- package/lib/module/features/remoteControls.js +13 -92
- package/lib/module/features/remoteControls.js.map +1 -1
- package/lib/module/features/sleepTimer.js +13 -1
- package/lib/module/features/sleepTimer.js.map +1 -1
- package/lib/module/test-utils/reactNativeStub.js +58 -0
- package/lib/module/test-utils/reactNativeStub.js.map +1 -0
- package/lib/module/utils/LazyNativeEmitter.js +28 -14
- package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/module/utils/NativeUpdatedValue.js +31 -13
- package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/module/utils/getTrackIdentity.js +20 -0
- package/lib/module/utils/getTrackIdentity.js.map +1 -0
- package/lib/module/utils/useNativeValueRefreshedBy.js +29 -0
- package/lib/module/utils/useNativeValueRefreshedBy.js.map +1 -0
- package/lib/module/web/NativeAudioBrowser.js +201 -76
- package/lib/module/web/NativeAudioBrowser.js.map +1 -1
- package/lib/module/web/TrackPlayer/LoadAttempt.js +32 -0
- package/lib/module/web/TrackPlayer/LoadAttempt.js.map +1 -0
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +18 -2
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
- package/lib/module/web/TrackPlayer/Player.js +254 -39
- package/lib/module/web/TrackPlayer/Player.js.map +1 -1
- package/lib/module/web/TrackPlayer/PlayingStateFactory.js +1 -1
- package/lib/module/web/TrackPlayer/QueueManager.js +14 -0
- package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -1
- package/lib/module/web/TrackPlayer/QueuePlayer.js +33 -12
- package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -1
- package/lib/module/web/browser/BrowserManager.js +175 -100
- package/lib/module/web/browser/BrowserManager.js.map +1 -1
- package/lib/module/web/browser/FavoriteManager.js +31 -21
- package/lib/module/web/browser/FavoriteManager.js.map +1 -1
- package/lib/module/web/browser/NavigationErrorManager.js +3 -1
- package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
- package/lib/module/web/browser/SearchManager.js +18 -23
- package/lib/module/web/browser/SearchManager.js.map +1 -1
- package/lib/module/web/browser/assertBrowsePageShape.js +2 -2
- package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -1
- package/lib/module/web/browser/classifyTrackNavigation.js +9 -9
- package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -1
- package/lib/module/web/browser/sections.js +83 -0
- package/lib/module/web/browser/sections.js.map +1 -0
- package/lib/module/web/http/RequestConfigBuilder.js +110 -27
- package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/module/web/http/followMediaRedirect.js +215 -0
- package/lib/module/web/http/followMediaRedirect.js.map +1 -0
- package/lib/module/web/player/NowPlayingManager.js +4 -3
- package/lib/module/web/player/NowPlayingManager.js.map +1 -1
- package/lib/module/web/util/BrowserPathHelper.js +62 -11
- package/lib/module/web/util/BrowserPathHelper.js.map +1 -1
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/AudioBrowser.d.ts +1 -1
- package/lib/typescript/src/AudioBrowser.d.ts.map +1 -1
- package/lib/typescript/src/features/browser-config.d.ts.map +1 -1
- package/lib/typescript/src/features/browser.d.ts +10 -2
- package/lib/typescript/src/features/browser.d.ts.map +1 -1
- package/lib/typescript/src/features/carConnection.d.ts +1 -1
- package/lib/typescript/src/features/equalizer.d.ts +1 -1
- package/lib/typescript/src/features/errors.d.ts +3 -3
- package/lib/typescript/src/features/favorites.d.ts +14 -11
- package/lib/typescript/src/features/favorites.d.ts.map +1 -1
- package/lib/typescript/src/features/gate.d.ts +18 -2
- package/lib/typescript/src/features/gate.d.ts.map +1 -1
- package/lib/typescript/src/features/metadata.d.ts +20 -3
- package/lib/typescript/src/features/metadata.d.ts.map +1 -1
- package/lib/typescript/src/features/network.d.ts +1 -1
- package/lib/typescript/src/features/nowPlaying.d.ts +1 -1
- package/lib/typescript/src/features/output.d.ts +1 -1
- package/lib/typescript/src/features/playback/controls.d.ts +4 -2
- package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/playWhenReady.d.ts +1 -1
- package/lib/typescript/src/features/playback/playing.d.ts +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/rate.d.ts +8 -1
- package/lib/typescript/src/features/playback/rate.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/state.d.ts +3 -4
- package/lib/typescript/src/features/playback/state.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/volume.d.ts +1 -1
- package/lib/typescript/src/features/player/options.d.ts +108 -56
- package/lib/typescript/src/features/player/options.d.ts.map +1 -1
- package/lib/typescript/src/features/player/setup.d.ts +14 -4
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
- package/lib/typescript/src/features/player/validateOptions.d.ts +2 -0
- package/lib/typescript/src/features/player/validateOptions.d.ts.map +1 -0
- package/lib/typescript/src/features/queue/activeTrack.d.ts +9 -2
- package/lib/typescript/src/features/queue/activeTrack.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/queue.d.ts +7 -4
- package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/repeatMode.d.ts +1 -1
- package/lib/typescript/src/features/queue/shuffle.d.ts +1 -1
- package/lib/typescript/src/features/remoteControls.d.ts +23 -22
- package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
- package/lib/typescript/src/test-utils/reactNativeStub.d.ts +36 -0
- package/lib/typescript/src/test-utils/reactNativeStub.d.ts.map +1 -0
- package/lib/typescript/src/types/browser-native.d.ts +3 -2
- package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-nodes.d.ts +387 -126
- package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
- package/lib/typescript/src/types/browser.d.ts +93 -61
- package/lib/typescript/src/types/browser.d.ts.map +1 -1
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +19 -16
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +24 -19
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
- package/lib/typescript/src/utils/getTrackIdentity.d.ts +18 -0
- package/lib/typescript/src/utils/getTrackIdentity.d.ts.map +1 -0
- package/lib/typescript/src/utils/resolveAssetSource.d.ts +1 -2
- package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
- package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts +21 -0
- package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts.map +1 -0
- package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +1 -2
- package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +4 -2
- package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +2 -2
- package/nitrogen/generated/android/c++/JAndroidAudioOffloadSettings.hpp +2 -2
- package/nitrogen/generated/android/c++/JAndroidOptions.hpp +12 -12
- package/nitrogen/generated/android/c++/JAndroidPlayerWakeMode.hpp +2 -2
- package/nitrogen/generated/android/c++/JAppKilledPlaybackBehavior.hpp +2 -2
- package/nitrogen/generated/android/c++/JArtworkRendering.hpp +58 -0
- package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +10 -5
- package/nitrogen/generated/android/c++/JArtworkVariants.hpp +2 -2
- package/nitrogen/generated/android/c++/JBatteryOptimizationStatus.hpp +2 -2
- package/nitrogen/generated/android/c++/JBatteryOptimizationStatusChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JBatteryWarningPendingChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JBrowseError.hpp +2 -2
- package/nitrogen/generated/android/c++/JBrowseResult.hpp +19 -7
- package/nitrogen/generated/android/c++/JBrowserSourceCallbackParam.hpp +2 -2
- package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +2 -2
- package/nitrogen/generated/android/c++/JCarPlayPlayingIndicatorLocation.hpp +58 -0
- package/nitrogen/generated/android/c++/JCarPlaySiriListButtonPosition.hpp +2 -2
- package/nitrogen/generated/android/c++/JCardImage.hpp +58 -0
- package/nitrogen/generated/android/c++/JChapterMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JEqualizerSettings.hpp +10 -10
- package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +10 -5
- package/nitrogen/generated/android/c++/JFormatNavigationErrorParams.hpp +11 -5
- package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +10 -5
- package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +9 -9
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.hpp +4 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +9 -9
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +18 -12
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +10 -4
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__string__.hpp +102 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +18 -6
- package/nitrogen/generated/android/c++/JFunc_void.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_BatteryOptimizationStatusChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_BatteryWarningPendingChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_EqualizerSettings.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_NavigationErrorEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -12
- package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackPlayWhenReadyChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackProgressUpdatedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackQueueEndedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_PlayingState.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpBackwardEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpForwardEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemotePlayIdEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemotePlaySearchEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemoteSeekEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemoteSkipEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RepeatModeChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_TrackMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_double.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_FormattedNavigationError_.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +17 -5
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_ChapterMetadata_.hpp +16 -16
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +24 -18
- package/nitrogen/generated/android/c++/JGate.hpp +2 -2
- package/nitrogen/generated/android/c++/JGateDecision.hpp +2 -2
- package/nitrogen/generated/android/c++/JGateEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JGateReason.hpp +2 -2
- package/nitrogen/generated/android/c++/JGridTile.hpp +64 -0
- package/nitrogen/generated/android/c++/JHttpMethod.hpp +2 -2
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +77 -53
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +3 -3
- package/nitrogen/generated/android/c++/JIOSCategory.hpp +2 -2
- package/nitrogen/generated/android/c++/JIOSCategoryMode.hpp +2 -2
- package/nitrogen/generated/android/c++/JIOSCategoryOptions.hpp +2 -2
- package/nitrogen/generated/android/c++/JIOSCategoryPolicy.hpp +2 -2
- package/nitrogen/generated/android/c++/JIOSOptions.hpp +17 -11
- package/nitrogen/generated/android/c++/JImageContext.hpp +2 -2
- package/nitrogen/generated/android/c++/JImageQueryParams.hpp +2 -2
- package/nitrogen/generated/android/c++/JImageShape.hpp +58 -0
- package/nitrogen/generated/android/c++/JImageSource.hpp +2 -2
- package/nitrogen/generated/android/c++/JMediaReference.hpp +2 -2
- package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +10 -5
- package/nitrogen/generated/android/c++/JMediaTransformParams.hpp +2 -2
- package/nitrogen/generated/android/c++/JNativeAndroidSetupOptions.hpp +2 -2
- package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +48 -21
- package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +2 -2
- package/nitrogen/generated/android/c++/JNativeIOSSetupOptions.hpp +10 -10
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +16 -4
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +17 -14
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +9 -12
- package/nitrogen/generated/android/c++/JNavigationError.hpp +2 -2
- package/nitrogen/generated/android/c++/JNavigationErrorEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JNavigationErrorKind.hpp +58 -0
- package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +2 -2
- package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +12 -12
- package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +17 -11
- package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +2 -2
- package/nitrogen/generated/android/c++/JOptions.hpp +9 -12
- package/nitrogen/generated/android/c++/JOutput.hpp +2 -2
- package/nitrogen/generated/android/c++/JOutputType.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlayback.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +10 -5
- package/nitrogen/generated/android/c++/JPlaybackError.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackPlayWhenReadyChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackProgressUpdatedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackQueueEndedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackState.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +7 -13
- package/nitrogen/generated/android/c++/JPlayingState.hpp +2 -2
- package/nitrogen/generated/android/c++/JProgress.hpp +2 -2
- package/nitrogen/generated/android/c++/{JNotificationButton.hpp → JRemoteButton.hpp} +19 -19
- package/nitrogen/generated/android/c++/JRemoteButtonLayout.hpp +86 -0
- package/nitrogen/generated/android/c++/JRemoteJumpBackwardEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRemoteJumpForwardEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRemotePlayIdEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRemotePlaySearchEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRemoteSeekEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRemoteSkipEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRepeatMode.hpp +2 -2
- package/nitrogen/generated/android/c++/JRepeatModeChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRequestConfig.hpp +2 -2
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +67 -59
- package/nitrogen/generated/android/c++/JRetryConfig.hpp +2 -2
- package/nitrogen/generated/android/c++/JSearchMode.hpp +2 -2
- package/nitrogen/generated/android/c++/JSearchParams.hpp +2 -2
- package/nitrogen/generated/android/c++/JSection.hpp +116 -0
- package/nitrogen/generated/android/c++/JSectionStyle.hpp +96 -0
- package/nitrogen/generated/android/c++/JSleepTimer.hpp +4 -4
- package/nitrogen/generated/android/c++/JSleepTimerEndOfTrack.hpp +2 -2
- package/nitrogen/generated/android/c++/JSleepTimerTime.hpp +2 -2
- package/nitrogen/generated/android/c++/JStallReason.hpp +2 -2
- package/nitrogen/generated/android/c++/JStyleDisplay.hpp +58 -0
- package/nitrogen/generated/android/c++/JTimedMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JTrack.hpp +27 -48
- package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +18 -12
- package/nitrogen/generated/android/c++/JTrackMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JTrackRequest.hpp +2 -2
- package/nitrogen/generated/android/c++/JTrackStyle.hpp +47 -19
- package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +2 -2
- package/nitrogen/generated/android/c++/JVariant_Boolean_AndroidAudioOffloadSettings.hpp +3 -3
- package/nitrogen/generated/android/c++/JVariant_Boolean_RetryConfig.hpp +3 -3
- package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +3 -3
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.hpp +75 -0
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +20 -8
- package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioOffloadSettings.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +20 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoritesMatchMode.kt → ArtworkRendering.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +37 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkVariants.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryOptimizationStatusChangedEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryWarningPendingChangedEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseError.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseResult.kt +16 -7
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowserSourceCallbackParam.kt +15 -0
- 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/ChapterMetadata.kt +19 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/EqualizerSettings.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FavoriteChangedEvent.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNavigationErrorParams.kt +25 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__string__.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryOptimizationStatusChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryWarningPendingChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_EqualizerSettings.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_FavoriteChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_GateEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NavigationErrorEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NowPlayingMetadata.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Options.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Output.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Playback.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackActiveTrackChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackErrorEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackPlayWhenReadyChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackProgressUpdatedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackQueueEndedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlayingState.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpBackwardEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpForwardEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlayIdEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlaySearchEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSeekEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSkipEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RepeatModeChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TimedMetadata.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TrackMetadata.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_double.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_FormattedNavigationError_.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_ResolvedTrack_.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__string.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_ChapterMetadata_.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_Track_.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Gate.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateDecision.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GridTile.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +3 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +25 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageContext.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageQueryParams.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageShape.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageSource.kt +19 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaTransformParams.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeAndroidSetupOptions.kt +31 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +51 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeGateRequest.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeIOSSetupOptions.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationError.kt +19 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorKind.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +20 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +25 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Output.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Playback.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackActiveTrackChangedEvent.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackPlayWhenReadyChangedEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackProgressUpdatedEvent.kt +19 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackQueueEndedEvent.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +37 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayingState.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Progress.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NotificationButton.kt → RemoteButton.kt} +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButtonLayout.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpBackwardEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpForwardEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlayIdEvent.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlaySearchEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSeekEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSkipEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RepeatModeChangedEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RequestConfig.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +67 -15
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Section.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SectionStyle.kt +86 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimer.kt +18 -8
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerEndOfTrack.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerTime.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StyleDisplay.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TimedMetadata.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +55 -12
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackLoadEvent.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackMetadata.kt +43 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +58 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +31 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_AndroidAudioOffloadSettings.kt +16 -7
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_RetryConfig.kt +16 -7
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_NullType_Double.kt +16 -7
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Variant_NullType_NotificationButtonLayout.kt → Variant_NullType_RemoteButtonLayout.kt} +24 -15
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +18 -8
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +16 -7
- package/nitrogen/generated/ios/AudioBrowser+autolinking.rb +2 -0
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +38 -29
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +779 -665
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +34 -16
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +36 -18
- package/nitrogen/generated/ios/swift/AndroidOptions.swift +12 -12
- package/nitrogen/generated/ios/swift/ArtworkRendering.swift +40 -0
- package/nitrogen/generated/ios/swift/BrowseResult.swift +12 -0
- package/nitrogen/generated/ios/swift/CarPlayPlayingIndicatorLocation.swift +40 -0
- package/nitrogen/generated/ios/swift/CardImage.swift +40 -0
- package/nitrogen/generated/ios/swift/FormatNavigationErrorParams.swift +7 -2
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__string__.swift +54 -0
- package/nitrogen/generated/ios/swift/GridTile.swift +48 -0
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +2 -2
- package/nitrogen/generated/ios/swift/IOSOptions.swift +7 -2
- package/nitrogen/generated/ios/swift/ImageShape.swift +40 -0
- package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +52 -5
- package/nitrogen/generated/ios/swift/NavigationErrorKind.swift +40 -0
- package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +12 -12
- package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +12 -1
- package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +8 -27
- package/nitrogen/generated/ios/swift/{NotificationButton.swift → RemoteButton.swift} +6 -6
- package/nitrogen/generated/ios/swift/RemoteButtonLayout.swift +57 -0
- package/nitrogen/generated/ios/swift/ResolvedTrack.swift +62 -73
- package/nitrogen/generated/ios/swift/Section.swift +82 -0
- package/nitrogen/generated/ios/swift/SectionStyle.swift +133 -0
- package/nitrogen/generated/ios/swift/SleepTimer.swift +13 -0
- package/nitrogen/generated/ios/swift/StyleDisplay.swift +40 -0
- package/nitrogen/generated/ios/swift/Track.swift +28 -63
- package/nitrogen/generated/ios/swift/TrackStyle.swift +86 -22
- package/nitrogen/generated/ios/swift/Variant_Bool_AndroidAudioOffloadSettings.swift +12 -0
- package/nitrogen/generated/ios/swift/Variant_Bool_RetryConfig.swift +12 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +12 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_RemoteButtonLayout.swift +30 -0
- package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +13 -0
- package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +12 -0
- package/nitrogen/generated/shared/c++/AndroidOptions.hpp +8 -8
- package/nitrogen/generated/shared/c++/{FavoritesMatchMode.hpp → ArtworkRendering.hpp} +17 -17
- package/nitrogen/generated/shared/c++/CarPlayPlayingIndicatorLocation.hpp +76 -0
- package/nitrogen/generated/shared/c++/CardImage.hpp +76 -0
- package/nitrogen/generated/shared/c++/FormatNavigationErrorParams.hpp +9 -2
- package/nitrogen/generated/shared/c++/GridTile.hpp +84 -0
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +1 -1
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +1 -1
- package/nitrogen/generated/shared/c++/IOSOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/ImageShape.hpp +76 -0
- package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +10 -6
- package/nitrogen/generated/shared/c++/NavigationErrorKind.hpp +76 -0
- package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +8 -8
- package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +6 -9
- package/nitrogen/generated/shared/c++/{NotificationButton.hpp → RemoteButton.hpp} +19 -19
- package/nitrogen/generated/shared/c++/RemoteButtonLayout.hpp +94 -0
- package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +33 -37
- package/nitrogen/generated/shared/c++/Section.hpp +102 -0
- package/nitrogen/generated/shared/c++/SectionStyle.hpp +126 -0
- package/nitrogen/generated/shared/c++/StyleDisplay.hpp +76 -0
- package/nitrogen/generated/shared/c++/Track.hpp +18 -30
- package/nitrogen/generated/shared/c++/TrackStyle.hpp +73 -34
- package/package.json +24 -11
- package/src/AudioBrowser.ts +2 -1
- package/src/CLAUDE.md +52 -0
- package/src/features/battery.test.ts +79 -0
- package/src/features/browser-config.test.ts +21 -6
- package/src/features/browser-config.ts +12 -8
- package/src/features/browser.test.ts +1 -1
- package/src/features/browser.ts +11 -3
- package/src/features/carConnection.ts +1 -1
- package/src/features/equalizer.ts +1 -1
- package/src/features/errors.ts +3 -3
- package/src/features/favorites.ts +14 -11
- package/src/features/gate.ts +16 -1
- package/src/features/hook-wiring.test.ts +302 -0
- package/src/features/metadata.ts +20 -3
- package/src/features/network.ts +1 -1
- package/src/features/nowPlaying.ts +1 -1
- package/src/features/output.ts +1 -1
- package/src/features/playback/controls.ts +4 -2
- package/src/features/playback/playWhenReady.ts +1 -1
- package/src/features/playback/playing.ts +1 -1
- package/src/features/playback/progress.test.ts +169 -0
- package/src/features/playback/progress.ts +3 -2
- package/src/features/playback/rate.ts +8 -1
- package/src/features/playback/state.ts +3 -4
- package/src/features/playback/trackPlaybackTime.test.ts +16 -6
- package/src/features/playback/trackPlaybackTime.ts +1 -6
- package/src/features/playback/volume.ts +1 -1
- package/src/features/player/options.ts +126 -76
- package/src/features/player/setup.test.ts +24 -7
- package/src/features/player/setup.ts +22 -10
- package/src/features/player/validateOptions.ts +21 -0
- package/src/features/queue/activeTrack.ts +15 -4
- package/src/features/queue/queue.ts +13 -6
- package/src/features/queue/repeatMode.ts +1 -1
- package/src/features/queue/shuffle.ts +1 -1
- package/src/features/remoteControls.ts +13 -92
- package/src/features/sleepTimer.test.ts +172 -0
- package/src/features/sleepTimer.ts +9 -1
- package/src/nitro-stub-drift.test.ts +277 -0
- package/src/public-surface.test.ts +147 -0
- package/src/specs/audio-browser.nitro.ts +5 -4
- package/src/style-resolution.test.ts +210 -0
- package/src/test-utils/reactNativeStub.ts +60 -0
- package/src/types/browser-native.ts +7 -3
- package/src/types/browser-nodes.ts +403 -134
- package/src/types/browser.ts +97 -63
- package/src/utils/LazyNativeEmitter.ts +28 -15
- package/src/utils/NativeUpdatedValue.ts +29 -13
- package/src/utils/getTrackIdentity.ts +20 -0
- package/src/utils/useDebug.test.ts +182 -0
- package/src/utils/useNativeUpdatedValue.test.ts +103 -0
- package/src/utils/useNativeValueRefreshedBy.ts +38 -0
- package/src/web/NativeAudioBrowser.playWhenReady.test.ts +232 -2
- package/src/web/NativeAudioBrowser.ts +240 -83
- package/src/web/TrackPlayer/LoadAttempt.ts +29 -0
- package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +60 -13
- package/src/web/TrackPlayer/PlaybackStateMachine.ts +22 -6
- package/src/web/TrackPlayer/Player.dispatch.test.ts +5 -3
- package/src/web/TrackPlayer/Player.load.test.ts +137 -1
- package/src/web/TrackPlayer/Player.ts +284 -37
- package/src/web/TrackPlayer/PlayingStateFactory.test.ts +1 -1
- package/src/web/TrackPlayer/PlayingStateFactory.ts +1 -1
- package/src/web/TrackPlayer/QueueManager.test.ts +29 -0
- package/src/web/TrackPlayer/QueueManager.ts +14 -0
- package/src/web/TrackPlayer/QueuePlayer.ts +33 -14
- package/src/web/__tests__/lifecycle.test.ts +345 -0
- package/src/web/__tests__/lifecycleHarness.ts +351 -0
- package/src/web/__tests__/loadEdgeCases.test.ts +246 -0
- package/src/web/__tests__/loadSupersession.test.ts +175 -0
- package/src/web/__tests__/retry.test.ts +169 -0
- package/src/web/browser/BrowserManager.ts +209 -111
- package/src/web/browser/FavoriteManager.test.ts +84 -0
- package/src/web/browser/FavoriteManager.ts +28 -23
- package/src/web/browser/NavigationErrorManager.ts +3 -1
- package/src/web/browser/SearchManager.test.ts +75 -0
- package/src/web/browser/SearchManager.ts +25 -28
- package/src/web/browser/__tests__/artwork-resolution.test.ts +117 -0
- package/src/web/browser/__tests__/layer-resolver.test.ts +35 -0
- package/src/web/browser/__tests__/search-artwork.test.ts +46 -0
- package/src/web/browser/__tests__/search-navigation.test.ts +76 -0
- package/src/web/browser/assertBrowsePageShape.test.ts +1 -1
- package/src/web/browser/assertBrowsePageShape.ts +5 -3
- package/src/web/browser/classifyTrackNavigation.test.ts +10 -8
- package/src/web/browser/classifyTrackNavigation.ts +9 -9
- package/src/web/browser/parseSearchResponse.test.ts +8 -2
- package/src/web/browser/sections.test.ts +91 -0
- package/src/web/browser/sections.ts +72 -0
- package/src/web/http/RequestConfigBuilder.test.ts +241 -1
- package/src/web/http/RequestConfigBuilder.ts +140 -33
- package/src/web/http/followMediaRedirect.test.ts +289 -0
- package/src/web/http/followMediaRedirect.ts +253 -0
- package/src/web/player/NowPlayingManager.ts +4 -3
- package/src/web/util/BrowserPathHelper.test.ts +68 -0
- package/src/web/util/BrowserPathHelper.ts +70 -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 +587 -0
- package/website/guide/carplay.md +650 -0
- package/website/guide/configuration.md +173 -0
- package/website/guide/equalizer.md +231 -0
- package/website/guide/errors.md +310 -0
- package/website/guide/favorites.md +154 -0
- package/website/guide/gate.md +143 -0
- package/website/guide/getting-started.md +46 -0
- package/website/guide/hooks.md +238 -0
- package/website/guide/live-streams.md +125 -0
- package/website/guide/metadata.md +239 -0
- package/website/guide/migrating-from-track-player.md +244 -0
- package/website/guide/native-callback-fetch.md +127 -0
- package/website/guide/network.md +86 -0
- package/website/guide/now-playing.md +175 -0
- package/website/guide/playback.md +328 -0
- package/website/guide/queue.md +300 -0
- package/website/guide/remote-controls.md +256 -0
- package/website/guide/search.md +255 -0
- package/website/guide/sleep-timer.md +268 -0
- package/website/guide/track.md +247 -0
- package/ios/Bridge.h +0 -8
- package/ios/Browser/MediaResolveComposer.swift +0 -114
- package/ios/CarPlay/ImageRowItem+CarPlay.swift +0 -19
- package/ios/Model/MediaURL.swift +0 -67
- package/ios/NowPlayingInfo/MediaItemProperty.swift +0 -78
- package/ios/NowPlayingInfo/NowPlayingInfoKeyValue.swift +0 -6
- package/ios/NowPlayingInfo/NowPlayingInfoProperty.swift +0 -220
- package/ios/Observer/PlayerItemNotificationObserver.swift +0 -119
- package/ios/Observer/PlayerItemPropertyObserver.swift +0 -133
- package/ios/Observer/PlayerStateObserver.swift +0 -50
- package/ios/Observer/PlayerTimeObserver.swift +0 -55
- package/ios/Option/PitchAlgorithms.swift +0 -17
- package/ios/Option/TimeEventFrequency.swift +0 -18
- package/ios/Player/LoadSeekCoordinator.swift +0 -99
- package/ios/Player/MediaLoaderDelegate.swift +0 -11
- package/ios/Player/PlaybackCoordinator.swift +0 -754
- package/ios/Player/PlaybackEffectHandler.swift +0 -54
- package/ios/Player/PlaybackErrorHandler.swift +0 -175
- package/ios/Player/PlaybackStateStore.swift +0 -27
- package/ios/Player/PlayingStateManager.swift +0 -33
- package/ios/Player/RetryManager.swift +0 -322
- package/ios/Player/SeekCompletionHandler.swift +0 -3
- package/ios/Player/SleepTimerHandling.swift +0 -15
- package/ios/Support/RNTrackPlayer-Bridging-Header.h +0 -7
- package/ios/Tests/LoadSeekCoordinatorTests.swift +0 -325
- package/ios/Tests/MediaResolveTests.swift +0 -126
- package/ios/Tests/OnceValueTests.swift +0 -79
- package/ios/Tests/PlaybackErrorHandlerTests.swift +0 -547
- package/ios/Tests/PlaybackStateStoreTests.swift +0 -48
- package/ios/Tests/PlayingStateManagerTests.swift +0 -57
- package/ios/Tests/RetryManagerTests.swift +0 -89
- package/ios/TrackPlayer.swift +0 -1014
- package/ios/TrackPlayerCallbacks.swift +0 -86
- package/ios/Util/MetadataAdapter.swift +0 -131
- package/ios/Util/OnceValue.swift +0 -104
- package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +0 -58
- package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +0 -58
- package/nitrogen/generated/android/c++/JImageRowItem.hpp +0 -105
- package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +0 -94
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +0 -26
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +0 -71
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +0 -26
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +0 -75
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FavoriteConfig.kt +0 -38
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +0 -68
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +0 -50
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +0 -53
- package/nitrogen/generated/ios/swift/FavoriteConfig.swift +0 -29
- package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +0 -40
- package/nitrogen/generated/ios/swift/ImageRowItem.swift +0 -195
- package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +0 -92
- package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +0 -18
- package/nitrogen/generated/ios/swift/Variant_NullType_NotificationButtonLayout.swift +0 -18
- package/nitrogen/generated/shared/c++/FavoriteConfig.hpp +0 -84
- package/nitrogen/generated/shared/c++/ImageRowItem.hpp +0 -129
- package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +0 -102
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
import NitroModules
|
|
3
3
|
#endif
|
|
4
4
|
|
|
5
|
-
///
|
|
6
|
-
|
|
7
|
-
/// so HybridAudioBrowser implements both automatically.
|
|
8
|
-
@MainActor protocol PlaybackCoordinatorCallbacks: AnyObject {
|
|
5
|
+
/// What the Player reports, in Nitro types. HybridAudioBrowser implements it.
|
|
6
|
+
@MainActor protocol PlayerCallbacks: AnyObject {
|
|
9
7
|
func playerDidChangePlayback(_ playback: Playback)
|
|
10
8
|
func playerDidChangeActiveTrack(_ event: PlaybackActiveTrackChangedEvent)
|
|
11
9
|
func playerDidUpdateProgress(_ event: PlaybackProgressUpdatedEvent)
|
|
@@ -21,4 +19,5 @@
|
|
|
21
19
|
/// (those resume), and no retry is pending (a live-stream reconnect must keep the session). The
|
|
22
20
|
/// host may release the audio session (debounced) so other apps' audio can resume.
|
|
23
21
|
func playerShouldReleaseSession()
|
|
22
|
+
func playerDidChangeSleepTimer(_ state: SleepTimerState?)
|
|
24
23
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
#if canImport(NitroModules)
|
|
4
|
+
import NitroModules
|
|
5
|
+
#endif
|
|
6
|
+
|
|
7
|
+
/// What the media stack reports to the Player.
|
|
8
|
+
enum EngineEvent {
|
|
9
|
+
/// The loaded item is now current and observed.
|
|
10
|
+
case itemPrepared(likelyToKeepUp: Bool)
|
|
11
|
+
/// Loading the asset failed; the retry loop classifies the error.
|
|
12
|
+
case loadFailed(Error)
|
|
13
|
+
/// The asset loaded but cannot play.
|
|
14
|
+
case unplayable
|
|
15
|
+
/// The source is not a URL.
|
|
16
|
+
case invalidSource(String)
|
|
17
|
+
/// The player or its item failed, with the HTTP status the server last answered, if any.
|
|
18
|
+
case failed(Error?, httpStatusCode: Int?)
|
|
19
|
+
case likelyToKeepUp(Bool)
|
|
20
|
+
/// `waitingForNoItem`: the player waits because it has no item to play.
|
|
21
|
+
case timeControlStatus(PlayerTimeControlStatus, waitingForNoItem: Bool)
|
|
22
|
+
/// Playback crossed the first millisecond.
|
|
23
|
+
case audioDidStart
|
|
24
|
+
case playedToEnd
|
|
25
|
+
/// The buffer emptied mid-playback.
|
|
26
|
+
case stalled
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// The media stack under the Player: the AVPlayer and its items, media loading, now playing and
|
|
30
|
+
/// the remote commands. It carries out what the Player decides and reports what it observes
|
|
31
|
+
/// through `onEvent`; it holds no playback policy. AVPlayerEngine is the one implementation;
|
|
32
|
+
/// tests use a mock.
|
|
33
|
+
@MainActor protocol PlayerEngine: AnyObject {
|
|
34
|
+
var onEvent: (@MainActor (EngineEvent) -> Void)? { get set }
|
|
35
|
+
|
|
36
|
+
// MARK: The current item
|
|
37
|
+
|
|
38
|
+
var hasItem: Bool { get }
|
|
39
|
+
var hasLoadedAsset: Bool { get }
|
|
40
|
+
var currentTime: Double { get }
|
|
41
|
+
var duration: Double { get }
|
|
42
|
+
var bufferedPosition: Double { get }
|
|
43
|
+
/// The position a reload resumes from: nil without an item, or for an indefinite duration.
|
|
44
|
+
var resumePosition: Double? { get }
|
|
45
|
+
/// The end of a live stream's seekable window, when it has one.
|
|
46
|
+
var liveEdge: Double? { get }
|
|
47
|
+
var isPlaybackLikelyToKeepUp: Bool { get }
|
|
48
|
+
var isAirPlayRoute: Bool { get }
|
|
49
|
+
/// 0–1; ramped by the sleep-timer fade.
|
|
50
|
+
var volume: Float { get set }
|
|
51
|
+
|
|
52
|
+
// MARK: Loading
|
|
53
|
+
|
|
54
|
+
/// Runs the media-URL resolver for `track`, so a short-lived URL is minted afresh, and loads
|
|
55
|
+
/// the result.
|
|
56
|
+
func resolveAndLoad(src: String, track: Track)
|
|
57
|
+
func cancelLoading()
|
|
58
|
+
/// Drops the asset and stops observing the item, leaving it in place for the reload.
|
|
59
|
+
func dropAsset()
|
|
60
|
+
/// Drops the asset and removes the item.
|
|
61
|
+
func clearItem()
|
|
62
|
+
func stopObservingItem()
|
|
63
|
+
/// Replaces the AVPlayer: every handle to the old one is invalid.
|
|
64
|
+
func recreate()
|
|
65
|
+
|
|
66
|
+
// MARK: Transport
|
|
67
|
+
|
|
68
|
+
func play()
|
|
69
|
+
func pause()
|
|
70
|
+
/// Stages `rate` for the next play; applies it now only when `playing`, since a nonzero
|
|
71
|
+
/// AVPlayer rate is a play.
|
|
72
|
+
func setRate(_ rate: Float, playing: Bool)
|
|
73
|
+
/// Seeks the current item exactly; `completion` runs on the main actor.
|
|
74
|
+
func seek(to seconds: Double, completion: @escaping @MainActor (Bool) -> Void)
|
|
75
|
+
func applyTimePitchAlgorithm()
|
|
76
|
+
|
|
77
|
+
// MARK: Now playing and remote commands
|
|
78
|
+
|
|
79
|
+
/// Renders silence so iOS elects the app onto the now-playing surfaces (ADR 0005).
|
|
80
|
+
func primeNowPlaying()
|
|
81
|
+
func loadNowPlayingMetadata(for track: Track)
|
|
82
|
+
func clearNowPlaying()
|
|
83
|
+
func updateRemoteRepeatMode(_ mode: RepeatMode)
|
|
84
|
+
func updateRemoteShuffleMode(_ enabled: Bool)
|
|
85
|
+
/// Greys out next/previous on the remote surfaces when the queue has nowhere to skip.
|
|
86
|
+
func updateSkipAvailability(canNext: Bool, canPrevious: Bool)
|
|
87
|
+
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
/// Decouples
|
|
2
|
-
///
|
|
1
|
+
/// Decouples Player from AVFoundation enum types.
|
|
2
|
+
/// AVPlayerEngine maps from AVPlayer.TimeControlStatus → PlayerTimeControlStatus at the call boundary.
|
|
3
3
|
enum PlayerTimeControlStatus {
|
|
4
4
|
case paused, waitingToPlayAtSpecifiedRate, playing
|
|
5
5
|
}
|
|
6
|
-
|
|
7
|
-
enum PlayerItemStatus {
|
|
8
|
-
case unknown, readyToPlay, failed
|
|
9
|
-
}
|
|
@@ -3,9 +3,16 @@ import Foundation
|
|
|
3
3
|
import NitroModules
|
|
4
4
|
#endif
|
|
5
5
|
|
|
6
|
-
///
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/// What a queue mutation changed, reported once the queue has settled.
|
|
7
|
+
struct QueueChange: Equatable {
|
|
8
|
+
/// The track list changed.
|
|
9
|
+
var tracks = false
|
|
10
|
+
/// A different track became current, or the current track was cleared.
|
|
11
|
+
var currentTrack = false
|
|
12
|
+
|
|
13
|
+
static let none = QueueChange()
|
|
14
|
+
static let tracksOnly = QueueChange(tracks: true)
|
|
15
|
+
static let tracksAndCurrent = QueueChange(tracks: true, currentTrack: true)
|
|
9
16
|
}
|
|
10
17
|
|
|
11
18
|
/// Result of a navigation action (next/previous/skipTo).
|
|
@@ -19,11 +26,9 @@ enum QueueNavigationResult {
|
|
|
19
26
|
}
|
|
20
27
|
|
|
21
28
|
/// Pure queue logic: tracks, indices, shuffle, repeat.
|
|
22
|
-
/// Has no knowledge of AVPlayer or playback —
|
|
29
|
+
/// Has no knowledge of AVPlayer or playback — Player and its engine own that.
|
|
23
30
|
@MainActor
|
|
24
31
|
class QueueManager {
|
|
25
|
-
weak var delegate: QueueManagerDelegate?
|
|
26
|
-
|
|
27
32
|
// MARK: - Stored Properties
|
|
28
33
|
|
|
29
34
|
/// The index of the current track. `-1` when there is no current track.
|
|
@@ -33,11 +38,7 @@ class QueueManager {
|
|
|
33
38
|
private(set) var queueSourcePath: String?
|
|
34
39
|
|
|
35
40
|
/// All tracks held by the queue.
|
|
36
|
-
private(set) var tracks: [Track] = []
|
|
37
|
-
didSet {
|
|
38
|
-
delegate?.queueDidChangeTracks(tracks)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
+
private(set) var tracks: [Track] = []
|
|
41
42
|
|
|
42
43
|
/// The shuffle order for randomized playback.
|
|
43
44
|
private(set) var shuffleOrder = ShuffleOrder()
|
|
@@ -45,8 +46,15 @@ class QueueManager {
|
|
|
45
46
|
/// The repeat mode for the queue. Plain property — no side effects.
|
|
46
47
|
var repeatMode: RepeatMode = .off
|
|
47
48
|
|
|
48
|
-
/// Whether shuffle mode is enabled.
|
|
49
|
-
var shuffleEnabled: Bool = false
|
|
49
|
+
/// Whether shuffle mode is enabled.
|
|
50
|
+
var shuffleEnabled: Bool = false {
|
|
51
|
+
didSet {
|
|
52
|
+
// Re-pin on enable: the existing order has the current track wherever it happened to land,
|
|
53
|
+
// so without this, turning shuffle on near the end of the queue ends it right away.
|
|
54
|
+
guard shuffleEnabled, shuffleEnabled != oldValue else { return }
|
|
55
|
+
shuffleOrder.reshuffle(keepingFirst: currentIndex)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
50
58
|
|
|
51
59
|
// MARK: - Computed Properties
|
|
52
60
|
|
|
@@ -196,41 +204,36 @@ class QueueManager {
|
|
|
196
204
|
return .trackChanged
|
|
197
205
|
}
|
|
198
206
|
|
|
199
|
-
// MARK: - Mutations
|
|
207
|
+
// MARK: - Mutations
|
|
200
208
|
|
|
201
|
-
/// Replace the entire queue with new tracks.
|
|
202
|
-
/// Returns `true` (current track always changes).
|
|
209
|
+
/// Replace the entire queue with new tracks. The current track always changes.
|
|
203
210
|
@discardableResult
|
|
204
|
-
func setQueue(_ newTracks: [Track], initialIndex: Int = 0, sourcePath: String? = nil) ->
|
|
211
|
+
func setQueue(_ newTracks: [Track], initialIndex: Int = 0, sourcePath: String? = nil) -> QueueChange {
|
|
205
212
|
let clampedIndex = max(0, min(initialIndex, newTracks.count - 1))
|
|
206
213
|
currentIndex = clampedIndex
|
|
207
214
|
queueSourcePath = sourcePath
|
|
208
215
|
tracks = newTracks
|
|
209
|
-
shuffleOrder = ShuffleOrder(length: newTracks.count)
|
|
210
|
-
return
|
|
216
|
+
shuffleOrder = ShuffleOrder(length: newTracks.count, firstIndex: clampedIndex)
|
|
217
|
+
return .tracksAndCurrent
|
|
211
218
|
}
|
|
212
219
|
|
|
213
|
-
/// Add tracks to the end of the queue.
|
|
214
|
-
/// Returns `true` if the queue was empty (a new current track was set).
|
|
220
|
+
/// Add tracks to the end of the queue. The current track changes only when the queue was empty.
|
|
215
221
|
@discardableResult
|
|
216
|
-
func add(_ newTracks: [Track], initialIndex: Int = 0) ->
|
|
217
|
-
guard !newTracks.isEmpty else { return
|
|
222
|
+
func add(_ newTracks: [Track], initialIndex: Int = 0) -> QueueChange {
|
|
223
|
+
guard !newTracks.isEmpty else { return .none }
|
|
218
224
|
let wasEmpty = tracks.isEmpty
|
|
219
225
|
let insertIndex = tracks.count
|
|
220
226
|
tracks.append(contentsOf: newTracks)
|
|
227
|
+
if wasEmpty { return adoptInitialCurrent(initialIndex) }
|
|
221
228
|
shuffleOrder.insert(at: insertIndex, count: newTracks.count)
|
|
222
|
-
|
|
223
|
-
currentIndex = max(0, min(initialIndex, tracks.count - 1))
|
|
224
|
-
return true
|
|
225
|
-
}
|
|
226
|
-
return false
|
|
229
|
+
return .tracksOnly
|
|
227
230
|
}
|
|
228
231
|
|
|
229
|
-
/// Add tracks at a specific index in the queue.
|
|
230
|
-
///
|
|
232
|
+
/// Add tracks at a specific index in the queue. The current track changes only when the queue
|
|
233
|
+
/// was empty.
|
|
231
234
|
@discardableResult
|
|
232
|
-
func addAt(_ newTracks: [Track], at index: Int) throws ->
|
|
233
|
-
guard !newTracks.isEmpty else { return
|
|
235
|
+
func addAt(_ newTracks: [Track], at index: Int) throws -> QueueChange {
|
|
236
|
+
guard !newTracks.isEmpty else { return .none }
|
|
234
237
|
guard index >= 0, tracks.count >= index else {
|
|
235
238
|
throw TrackPlayerError.QueueError.invalidIndex(
|
|
236
239
|
index: index,
|
|
@@ -243,48 +246,68 @@ class QueueManager {
|
|
|
243
246
|
currentIndex += newTracks.count
|
|
244
247
|
}
|
|
245
248
|
tracks.insert(contentsOf: newTracks, at: index)
|
|
249
|
+
if wasEmpty { return adoptInitialCurrent(0) }
|
|
246
250
|
shuffleOrder.insert(at: index, count: newTracks.count)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
return .tracksOnly
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/// The queue was empty: `index` becomes the current track AND leads the
|
|
255
|
+
/// shuffle order. One operation because the two must not be separable —
|
|
256
|
+
/// forgetting the second half is the bug this exists to prevent.
|
|
257
|
+
///
|
|
258
|
+
/// `insert(at:count:)` drops new indices at *random* shuffle positions, so
|
|
259
|
+
/// without the pin the starting track can land last in the order, which reads
|
|
260
|
+
/// as `isLastInPlaybackOrder`: the queue "ends" (and fires
|
|
261
|
+
/// `playerDidEndQueue`) the moment the first track finishes. Pins
|
|
262
|
+
/// unconditionally, like `setQueue` — the order has to be sane whether or not
|
|
263
|
+
/// shuffle is on right now, since `shuffleEnabled`'s didSet only re-pins on
|
|
264
|
+
/// the off→on edge.
|
|
265
|
+
///
|
|
266
|
+
/// Returns the change, so callers can `return adoptInitialCurrent(…)`.
|
|
267
|
+
private func adoptInitialCurrent(_ index: Int) -> QueueChange {
|
|
268
|
+
currentIndex = max(0, min(index, tracks.count - 1))
|
|
269
|
+
shuffleOrder = ShuffleOrder(length: tracks.count, firstIndex: currentIndex)
|
|
270
|
+
return .tracksAndCurrent
|
|
252
271
|
}
|
|
253
272
|
|
|
254
|
-
/// Remove a track from the queue.
|
|
255
|
-
/// Returns `true` if the current track changed.
|
|
273
|
+
/// Remove a track from the queue. The current track changes when it is the one removed.
|
|
256
274
|
@discardableResult
|
|
257
|
-
func remove(_ index: Int) throws ->
|
|
275
|
+
func remove(_ index: Int) throws -> QueueChange {
|
|
258
276
|
try throwIfQueueEmpty()
|
|
259
277
|
try throwIfIndexInvalid(index: index)
|
|
260
278
|
tracks.remove(at: index)
|
|
261
279
|
shuffleOrder.remove(from: index, to: index + 1)
|
|
262
280
|
if index == currentIndex {
|
|
263
281
|
currentIndex = tracks.count > 0 ? currentIndex % tracks.count : -1
|
|
264
|
-
return
|
|
282
|
+
return .tracksAndCurrent
|
|
265
283
|
} else if index < currentIndex {
|
|
266
284
|
currentIndex -= 1
|
|
267
285
|
}
|
|
268
|
-
return
|
|
286
|
+
return .tracksOnly
|
|
269
287
|
}
|
|
270
288
|
|
|
271
|
-
/// Move a track in the queue from one position to another.
|
|
272
|
-
///
|
|
289
|
+
/// Move a track in the queue from one position to another. The current track never changes:
|
|
290
|
+
/// the pointer follows the playing track.
|
|
273
291
|
@discardableResult
|
|
274
|
-
func move(fromIndex: Int, toIndex: Int) throws ->
|
|
292
|
+
func move(fromIndex: Int, toIndex: Int) throws -> QueueChange {
|
|
275
293
|
try throwIfQueueEmpty()
|
|
276
294
|
try throwIfIndexInvalid(index: fromIndex, name: "fromIndex")
|
|
277
295
|
try throwIfIndexInvalid(index: toIndex, name: "toIndex", max: Int.max)
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
296
|
+
let track = tracks.remove(at: fromIndex)
|
|
297
|
+
let insertion = min(tracks.count, toIndex)
|
|
298
|
+
tracks.insert(track, at: insertion)
|
|
299
|
+
// Carry the moved track's shuffle position across the move. `insert(at:count:)`
|
|
300
|
+
// would drop it at a RANDOM position instead — reordering the queue would then
|
|
301
|
+
// silently reorder shuffled playback, and moving the playing track could land it
|
|
302
|
+
// last in the order, ending the queue at the next track boundary with tracks
|
|
303
|
+
// still unplayed (the failure `adoptInitialCurrent` guards against elsewhere).
|
|
304
|
+
// `remove` shifts every later position down by one, so re-inserting at the
|
|
305
|
+
// captured position restores the exact prior order.
|
|
306
|
+
let shufflePosition = shuffleOrder.shufflePosition(of: fromIndex)
|
|
284
307
|
shuffleOrder.remove(from: fromIndex, to: fromIndex + 1)
|
|
285
|
-
shuffleOrder.insert(
|
|
286
|
-
|
|
287
|
-
|
|
308
|
+
shuffleOrder.insert(
|
|
309
|
+
at: insertion, atShufflePosition: shufflePosition ?? shuffleOrder.count,
|
|
310
|
+
)
|
|
288
311
|
if currentIndex == fromIndex {
|
|
289
312
|
currentIndex = insertion
|
|
290
313
|
} else if fromIndex < currentIndex, insertion >= currentIndex {
|
|
@@ -292,35 +315,38 @@ class QueueManager {
|
|
|
292
315
|
} else if fromIndex > currentIndex, insertion <= currentIndex {
|
|
293
316
|
currentIndex += 1
|
|
294
317
|
}
|
|
295
|
-
return
|
|
318
|
+
return .tracksOnly
|
|
296
319
|
}
|
|
297
320
|
|
|
298
|
-
/// Remove all tracks and reset state.
|
|
299
|
-
/// Returns `true` if there was a current track to clear.
|
|
321
|
+
/// Remove all tracks and reset state. Does nothing when there is no current track.
|
|
300
322
|
@discardableResult
|
|
301
|
-
func clear() ->
|
|
302
|
-
guard currentIndex != -1 else { return
|
|
323
|
+
func clear() -> QueueChange {
|
|
324
|
+
guard currentIndex != -1 else { return .none }
|
|
303
325
|
currentIndex = -1
|
|
304
326
|
tracks.removeAll()
|
|
305
327
|
shuffleOrder.clear()
|
|
306
328
|
queueSourcePath = nil
|
|
307
|
-
return
|
|
329
|
+
return .tracksAndCurrent
|
|
308
330
|
}
|
|
309
331
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
func replace(_ index: Int, _ track: Track) {
|
|
332
|
+
/// Replace the track at a specific index; which index is current does not change.
|
|
333
|
+
/// Throws like every other index-taking mutation here, rather than trapping.
|
|
334
|
+
@discardableResult
|
|
335
|
+
func replace(_ index: Int, _ track: Track) throws -> QueueChange {
|
|
336
|
+
try throwIfIndexInvalid(index: index)
|
|
314
337
|
tracks[index] = track
|
|
338
|
+
return .tracksOnly
|
|
315
339
|
}
|
|
316
340
|
|
|
317
341
|
/// Remove all upcoming tracks (those after currentIndex).
|
|
318
|
-
|
|
319
|
-
|
|
342
|
+
@discardableResult
|
|
343
|
+
func removeUpcomingTracks() -> QueueChange {
|
|
344
|
+
guard !tracks.isEmpty else { return .none }
|
|
320
345
|
let nextIndex = currentIndex + 1
|
|
321
|
-
guard nextIndex < tracks.count else { return }
|
|
346
|
+
guard nextIndex < tracks.count else { return .none }
|
|
322
347
|
let end = tracks.count
|
|
323
348
|
tracks.removeSubrange(nextIndex ..< end)
|
|
324
349
|
shuffleOrder.remove(from: nextIndex, to: end)
|
|
350
|
+
return .tracksOnly
|
|
325
351
|
}
|
|
326
352
|
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import AVFoundation
|
|
2
|
+
import Foundation
|
|
3
|
+
#if canImport(NitroModules)
|
|
4
|
+
import NitroModules
|
|
5
|
+
#endif
|
|
6
|
+
import os.log
|
|
7
|
+
|
|
8
|
+
/// Abstracts `NetworkMonitor` so tests can fake connectivity. Sendable because
|
|
9
|
+
/// the network-restore race reads it from a task-group child.
|
|
10
|
+
protocol NetworkStatusProviding: AnyObject, Sendable {
|
|
11
|
+
var isOnline: Bool { get }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/// Distinguishes playback failures from media-load failures.
|
|
15
|
+
/// Each context carries the retry strategy and the fallback error classification.
|
|
16
|
+
public enum PlaybackErrorContext {
|
|
17
|
+
/// AVPlayer/AVPlayerItem status failure — retry from current time, fallback `.playbackFailed`.
|
|
18
|
+
case playback
|
|
19
|
+
/// MediaLoader key-value load failure — retry from start, fallback `.failedToLoadKeyValue`.
|
|
20
|
+
case mediaLoad
|
|
21
|
+
|
|
22
|
+
var startFromCurrentTime: Bool {
|
|
23
|
+
switch self {
|
|
24
|
+
case .playback: true
|
|
25
|
+
case .mediaLoad: false
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var fallbackError: TrackPlayerError.PlaybackError {
|
|
30
|
+
switch self {
|
|
31
|
+
case .playback: .playbackFailed
|
|
32
|
+
case .mediaLoad: .failedToLoadKeyValue
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// Retries failed loads: classifies each failure (`PlaybackFailure`), reports the ones it is
|
|
38
|
+
/// working on as advisory, and reloads after an exponential backoff until a budget runs out,
|
|
39
|
+
/// when it reports the error as terminal. Similar to Android's RetryLoadErrorHandlingPolicy.
|
|
40
|
+
///
|
|
41
|
+
/// Two duration budgets apply, chosen by whether the current Load has produced audio
|
|
42
|
+
/// (`hasPlayed`, ADR 0004): a short first-connect budget, since a stream that fails before ever
|
|
43
|
+
/// playing is usually dead and the listener is waiting for a verdict, and the full recovery
|
|
44
|
+
/// budget for a stream that played and dropped. The short budget counts only online time, and
|
|
45
|
+
/// while offline a scheduled retry fires as soon as connectivity returns.
|
|
46
|
+
@MainActor
|
|
47
|
+
final class RetryLoop {
|
|
48
|
+
private let logger = Logger(subsystem: "com.audiobrowser", category: "RetryLoop")
|
|
49
|
+
|
|
50
|
+
enum Policy {
|
|
51
|
+
case disabled
|
|
52
|
+
case infinite
|
|
53
|
+
case limited(maxRetries: Int)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private static let defaultMaxRetryDurationMs: Double = 120_000
|
|
57
|
+
private static let defaultFirstConnectMaxRetryDurationMs: Double = 12_000
|
|
58
|
+
|
|
59
|
+
/// Prevents surprising playback resumption after long periods offline.
|
|
60
|
+
private var maxRetryDuration: TimeInterval = defaultMaxRetryDurationMs / 1000
|
|
61
|
+
/// Bounds retries of a load that has never produced audio, while online.
|
|
62
|
+
private var firstConnectMaxRetryDuration: TimeInterval = defaultFirstConnectMaxRetryDurationMs / 1000
|
|
63
|
+
|
|
64
|
+
/// Whether the current Load has produced audio. Read from the Load, which a mid-play `reset()`
|
|
65
|
+
/// (the healthy-playback refill) leaves alone.
|
|
66
|
+
var hasPlayed: () -> Bool = { false }
|
|
67
|
+
/// Whether a retry is still wanted (the play intent); checked before and after the backoff.
|
|
68
|
+
var shouldRetry: () -> Bool = { true }
|
|
69
|
+
/// Reloads, from the current time or from the start.
|
|
70
|
+
var onRetry: ((Bool) -> Void)?
|
|
71
|
+
/// The retries gave up, or the failure cannot be retried.
|
|
72
|
+
var onError: ((TrackPlayerError.PlaybackError) -> Void)?
|
|
73
|
+
/// A failure a retry is now scheduled for, reported before the backoff so UIs can show the
|
|
74
|
+
/// cause while the state stays non-terminal.
|
|
75
|
+
var onRetryingError: ((TrackPlayerError.PlaybackError) -> Void)?
|
|
76
|
+
|
|
77
|
+
weak var networkMonitor: (any NetworkStatusProviding)?
|
|
78
|
+
|
|
79
|
+
/// The retry in flight; session release waits while there is one.
|
|
80
|
+
private(set) var pendingTask: Task<Void, Never>?
|
|
81
|
+
/// True only while a scheduled retry waits for connectivity to return, so a stall-driven
|
|
82
|
+
/// reconnect can defer to it rather than load twice.
|
|
83
|
+
private(set) var isWaitingForNetwork = false
|
|
84
|
+
/// Retries executed since the budgets last reset.
|
|
85
|
+
private(set) var attempts = 0
|
|
86
|
+
|
|
87
|
+
private var policy: Policy = .disabled
|
|
88
|
+
private var firstRetryTime: Date?
|
|
89
|
+
/// First failure observed while online for the current load: the first-connect budget's
|
|
90
|
+
/// clock. Never set while offline, and wiped by any offline observation, so an offline stretch
|
|
91
|
+
/// cannot burn the short budget.
|
|
92
|
+
private var firstOnlineRetryTime: Date?
|
|
93
|
+
|
|
94
|
+
private let sleep: @Sendable (TimeInterval) async throws -> Void
|
|
95
|
+
|
|
96
|
+
/// - Parameter sleep: Waits out a backoff or a connectivity poll; tests make it instant.
|
|
97
|
+
init(sleep: @escaping @Sendable (TimeInterval) async throws -> Void = { try await Task.sleep(for: .seconds($0)) }) {
|
|
98
|
+
self.sleep = sleep
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
var isEnabled: Bool {
|
|
102
|
+
if case .disabled = policy { return false }
|
|
103
|
+
return true
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// MARK: - Configuration
|
|
107
|
+
|
|
108
|
+
func updatePolicy(from config: Variant_Bool_RetryConfig?) {
|
|
109
|
+
maxRetryDuration = Self.defaultMaxRetryDurationMs / 1000
|
|
110
|
+
firstConnectMaxRetryDuration = Self.defaultFirstConnectMaxRetryDurationMs / 1000
|
|
111
|
+
switch config {
|
|
112
|
+
case nil:
|
|
113
|
+
policy = .disabled
|
|
114
|
+
case let .first(enabled):
|
|
115
|
+
policy = enabled ? .infinite : .disabled
|
|
116
|
+
case let .second(retryConfig):
|
|
117
|
+
maxRetryDuration = (retryConfig.maxRetryDurationMs ?? Self.defaultMaxRetryDurationMs) / 1000
|
|
118
|
+
firstConnectMaxRetryDuration =
|
|
119
|
+
(retryConfig.firstConnectMaxRetryDurationMs ?? Self.defaultFirstConnectMaxRetryDurationMs) / 1000
|
|
120
|
+
// No attempt cap: retry indefinitely, bounded only by the duration.
|
|
121
|
+
policy = retryConfig.maxRetries.map { .limited(maxRetries: Int($0)) } ?? .infinite
|
|
122
|
+
}
|
|
123
|
+
logger.debug("Retry policy: \(String(describing: self.policy)), max duration \(self.maxRetryDuration)s")
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// MARK: - Failures
|
|
127
|
+
|
|
128
|
+
func handleError(_ error: Error?, context: PlaybackErrorContext, httpStatusCode: Int? = nil) {
|
|
129
|
+
if let error {
|
|
130
|
+
let nsError = error as NSError
|
|
131
|
+
logger.error("[\(String(describing: context))] failure: domain=\(nsError.domain), code=\(nsError.code), localizedDescription=\(error.localizedDescription)")
|
|
132
|
+
} else {
|
|
133
|
+
logger.error("[\(String(describing: context))] failure with nil error")
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
let failure = PlaybackFailure.classify(error, httpStatusCode: httpStatusCode, fallback: context.fallbackError)
|
|
137
|
+
guard isEnabled, failure.retryable else {
|
|
138
|
+
logger.warning("Error not retryable, surfacing \(String(describing: failure.error))")
|
|
139
|
+
onError?(failure.error)
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
onRetryingError?(failure.error)
|
|
143
|
+
pendingTask?.cancel()
|
|
144
|
+
pendingTask = Task { [weak self] in
|
|
145
|
+
guard let self else { return }
|
|
146
|
+
let retried = await attemptRetry(startFromCurrentTime: context.startFromCurrentTime)
|
|
147
|
+
// Cancelled (track change, stop): stay silent, or the new track or a deliberate stop
|
|
148
|
+
// would flip to .error. The canceller owns the handle.
|
|
149
|
+
if Task.isCancelled { return }
|
|
150
|
+
if !retried { onError?(failure.error) }
|
|
151
|
+
pendingTask = nil
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/// Drops the retry in flight without touching the budgets.
|
|
156
|
+
func cancel() {
|
|
157
|
+
pendingTask?.cancel()
|
|
158
|
+
pendingTask = nil
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/// Drops the retry in flight and restarts the budgets.
|
|
162
|
+
func reset() {
|
|
163
|
+
cancel()
|
|
164
|
+
attempts = 0
|
|
165
|
+
firstRetryTime = nil
|
|
166
|
+
firstOnlineRetryTime = nil
|
|
167
|
+
isWaitingForNetwork = false
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// MARK: - Budgets
|
|
171
|
+
|
|
172
|
+
private var isOnline: Bool { networkMonitor?.isOnline ?? true }
|
|
173
|
+
|
|
174
|
+
/// The exhausted budget, or nil while budget remains. The recovery duration bounds everything,
|
|
175
|
+
/// offline waits included; the first-connect duration also bounds never-played loads, online
|
|
176
|
+
/// only.
|
|
177
|
+
private func exhaustedBudget() -> String? {
|
|
178
|
+
let now = Date()
|
|
179
|
+
if let start = firstRetryTime, now.timeIntervalSince(start) >= maxRetryDuration {
|
|
180
|
+
return "max retry duration (\(maxRetryDuration)s)"
|
|
181
|
+
}
|
|
182
|
+
if !hasPlayed(), isOnline, let start = firstOnlineRetryTime,
|
|
183
|
+
now.timeIntervalSince(start) >= firstConnectMaxRetryDuration
|
|
184
|
+
{
|
|
185
|
+
return "first-connect retry duration (\(firstConnectMaxRetryDuration)s)"
|
|
186
|
+
}
|
|
187
|
+
return nil
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/// 1 s, 1.5 s, 2.3 s, 3.4 s, then 5 s.
|
|
191
|
+
private var backoff: TimeInterval {
|
|
192
|
+
min(1.0 * pow(1.5, Double(attempts)), 5.0)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/// Waits out the backoff, or connectivity's return, then reloads. False when the policy, the
|
|
196
|
+
/// play intent or a budget says stop, or the wait was cancelled.
|
|
197
|
+
func attemptRetry(startFromCurrentTime: Bool) async -> Bool {
|
|
198
|
+
guard isEnabled, shouldRetry() else { return false }
|
|
199
|
+
if case let .limited(maxRetries) = policy, attempts >= maxRetries {
|
|
200
|
+
logger.info("Max retries (\(maxRetries)) exceeded, giving up")
|
|
201
|
+
return false
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if firstRetryTime == nil { firstRetryTime = Date() }
|
|
205
|
+
if isOnline {
|
|
206
|
+
if firstOnlineRetryTime == nil { firstOnlineRetryTime = Date() }
|
|
207
|
+
} else {
|
|
208
|
+
// Offline restarts the first-connect clock: the station gets its full online seconds
|
|
209
|
+
// again once connectivity returns.
|
|
210
|
+
firstOnlineRetryTime = nil
|
|
211
|
+
}
|
|
212
|
+
if let budget = exhaustedBudget() {
|
|
213
|
+
logger.info("\(budget) exceeded, giving up")
|
|
214
|
+
return false
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
logger.info("Scheduling retry after \(self.backoff)s")
|
|
218
|
+
guard await waitForDelayOrNetworkRestored(delaySeconds: backoff), !Task.isCancelled, shouldRetry() else {
|
|
219
|
+
return false
|
|
220
|
+
}
|
|
221
|
+
// Re-checked: the wait for connectivity may have been long.
|
|
222
|
+
if let budget = exhaustedBudget() {
|
|
223
|
+
logger.info("\(budget) exceeded after waiting, giving up")
|
|
224
|
+
return false
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
attempts += 1
|
|
228
|
+
logger.info("Executing retry #\(self.attempts)")
|
|
229
|
+
onRetry?(startFromCurrentTime)
|
|
230
|
+
return true
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// MARK: - Network-Aware Waiting
|
|
234
|
+
|
|
235
|
+
/// True when it is time to retry, false when the wait was cancelled.
|
|
236
|
+
private func waitForDelayOrNetworkRestored(delaySeconds: TimeInterval) async -> Bool {
|
|
237
|
+
guard let monitor = networkMonitor, !monitor.isOnline else {
|
|
238
|
+
return await (try? sleep(delaySeconds)) != nil
|
|
239
|
+
}
|
|
240
|
+
logger.debug("Device is offline, will retry immediately when connectivity is restored")
|
|
241
|
+
let sleep = sleep
|
|
242
|
+
return await withTaskGroup(of: Bool.self, returning: Bool.self) { group in
|
|
243
|
+
group.addTask { await (try? sleep(delaySeconds)) != nil }
|
|
244
|
+
group.addTask { [weak self] in await self?.waitForNetworkRestored(monitor: monitor) ?? false }
|
|
245
|
+
let result = await group.next() ?? false
|
|
246
|
+
group.cancelAll()
|
|
247
|
+
return result
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/// True when connectivity returned, false when cancelled.
|
|
252
|
+
private func waitForNetworkRestored(monitor: any NetworkStatusProviding) async -> Bool {
|
|
253
|
+
isWaitingForNetwork = true
|
|
254
|
+
defer { isWaitingForNetwork = false }
|
|
255
|
+
while !monitor.isOnline {
|
|
256
|
+
guard await (try? sleep(0.5)) != nil else { return false }
|
|
257
|
+
}
|
|
258
|
+
logger.info("Network restored, accelerating retry")
|
|
259
|
+
return true
|
|
260
|
+
}
|
|
261
|
+
}
|