react-native-audio-browser 0.2.0-next.23 → 0.2.0-next.25

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.
Files changed (38) hide show
  1. package/android/gradle.properties +1 -1
  2. package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +158 -120
  3. package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +6 -0
  4. package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +14 -0
  5. package/ios/Browser/BrowserPathHelper.swift +6 -2
  6. package/ios/CarPlay/CarPlayController.swift +5 -1
  7. package/ios/Extension/NavigationError+Conversion.swift +7 -0
  8. package/ios/HybridAudioBrowser.swift +4 -1
  9. package/ios/Tests/BrowserPathHelperTests.swift +11 -0
  10. package/lib/commonjs/web/browser/NavigationErrorManager.js +3 -1
  11. package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -1
  12. package/lib/commonjs/web/util/BrowserPathHelper.js +6 -0
  13. package/lib/commonjs/web/util/BrowserPathHelper.js.map +1 -1
  14. package/lib/module/web/browser/NavigationErrorManager.js +3 -1
  15. package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
  16. package/lib/module/web/util/BrowserPathHelper.js +6 -0
  17. package/lib/module/web/util/BrowserPathHelper.js.map +1 -1
  18. package/lib/typescript/src/types/browser.d.ts +8 -1
  19. package/lib/typescript/src/types/browser.d.ts.map +1 -1
  20. package/nitrogen/generated/android/c++/JFormatNavigationErrorParams.hpp +9 -3
  21. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.hpp +2 -0
  22. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +4 -0
  23. package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +2 -0
  24. package/nitrogen/generated/android/c++/JNavigationErrorKind.hpp +58 -0
  25. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNavigationErrorParams.kt +6 -3
  26. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorKind.kt +23 -0
  27. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +3 -0
  28. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +3 -0
  29. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +3 -0
  30. package/nitrogen/generated/ios/swift/FormatNavigationErrorParams.swift +7 -2
  31. package/nitrogen/generated/ios/swift/NavigationErrorKind.swift +40 -0
  32. package/nitrogen/generated/shared/c++/FormatNavigationErrorParams.hpp +9 -2
  33. package/nitrogen/generated/shared/c++/NavigationErrorKind.hpp +76 -0
  34. package/package.json +1 -1
  35. package/src/types/browser.ts +9 -1
  36. package/src/web/browser/NavigationErrorManager.ts +3 -1
  37. package/src/web/util/BrowserPathHelper.test.ts +16 -0
  38. package/src/web/util/BrowserPathHelper.ts +9 -0
@@ -3,4 +3,4 @@ AudioBrowser_minSdkVersion=23
3
3
  AudioBrowser_targetSdkVersion=35
4
4
  AudioBrowser_compileSdkVersion=35
5
5
  AudioBrowser_ndkVersion=27.1.12297006
6
- AudioBrowser_media3Version=1.11.0
6
+ AudioBrowser_media3Version=1.11.1
@@ -87,6 +87,7 @@ import com.margelo.nitro.audiobrowser.TimedMetadata
87
87
  import com.margelo.nitro.audiobrowser.Track
88
88
  import com.margelo.nitro.audiobrowser.TrackMetadata
89
89
  import com.margelo.nitro.audiobrowser.TransformableRequestConfig
90
+ import com.margelo.nitro.core.NullType
90
91
  import com.margelo.nitro.core.Promise
91
92
  import java.util.concurrent.TimeUnit
92
93
  import java.util.concurrent.atomic.AtomicReference
@@ -519,7 +520,15 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
519
520
  val default = defaultFormattedError(error)
520
521
  val formatter = _configuration.formatNavigationError ?: return default
521
522
  return formattedOrDefault(mainScope, default) {
522
- formatter(FormatNavigationErrorParams(error, default, path)).await()
523
+ formatter(
524
+ FormatNavigationErrorParams(
525
+ error,
526
+ default,
527
+ path,
528
+ BrowserPathHelper.navigationErrorKind(path),
529
+ )
530
+ )
531
+ .await()
523
532
  }
524
533
  }
525
534
 
@@ -908,24 +917,27 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
908
917
  // ============================================================================
909
918
 
910
919
  override fun load(track: Track) {
920
+ // Throws without a player, as on iOS: a track asked for and silently dropped hides a mistake.
921
+ val player = player
911
922
  launchInScope { player.load(track) }
912
923
  }
913
924
 
914
- override fun reset() = runBlockingOnMain {
915
- player.stop()
916
- player.clear()
917
- // clear() while IDLE emits no engine event, so the state machine never
918
- // leaves STOPPED — a reset queue is "nothing loaded".
919
- player.setPlaybackState(PlaybackState.NONE)
920
- }
925
+ override fun reset() =
926
+ commandPlayer("reset") { player ->
927
+ player.stop()
928
+ player.clear()
929
+ // clear() while IDLE emits no engine event, so the state machine never
930
+ // leaves STOPPED — a reset queue is "nothing loaded".
931
+ player.setPlaybackState(PlaybackState.NONE)
932
+ }
921
933
 
922
- override fun play() = runBlockingOnMain { player.play() }
934
+ override fun play() = commandPlayer("play") { it.play() }
923
935
 
924
- override fun pause() = runBlockingOnMain { player.pause() }
936
+ override fun pause() = commandPlayer("pause") { it.pause() }
925
937
 
926
- override fun togglePlayback() = runBlockingOnMain { player.togglePlayback() }
938
+ override fun togglePlayback() = commandPlayer("togglePlayback") { it.togglePlayback() }
927
939
 
928
- override fun stop() = runBlockingOnMain { player.stop() }
940
+ override fun stop() = commandPlayer("stop") { it.stop() }
929
941
 
930
942
  override fun setPlayWhenReady(playWhenReady: Boolean) = runBlockingOnMain {
931
943
  // Pre-setup this stages the intent for the player to come up with — never throws.
@@ -937,35 +949,41 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
937
949
  connectedService?.player?.playWhenReady ?: pendingPlayWhenReady ?: false
938
950
  }
939
951
 
940
- override fun seekTo(position: Double) = runBlockingOnMain {
941
- player.seekTo((position * 1000).toLong(), TimeUnit.MILLISECONDS)
942
- }
952
+ override fun seekTo(position: Double) =
953
+ commandPlayer("seekTo") { player ->
954
+ player.seekTo((position * 1000).toLong(), TimeUnit.MILLISECONDS)
955
+ }
943
956
 
944
- override fun seekBy(offset: Double) = runBlockingOnMain {
945
- player.seekBy((offset * 1000).toLong(), TimeUnit.MILLISECONDS)
946
- }
957
+ override fun seekBy(offset: Double) =
958
+ commandPlayer("seekBy") { player ->
959
+ player.seekBy((offset * 1000).toLong(), TimeUnit.MILLISECONDS)
960
+ }
947
961
 
948
- override fun seekToLiveEdge() = runBlockingOnMain { player.seekToLiveEdge() }
962
+ override fun seekToLiveEdge() = commandPlayer("seekToLiveEdge") { it.seekToLiveEdge() }
949
963
 
950
- override fun setVolume(level: Double) = runBlockingOnMain { player.volume = level.toFloat() }
964
+ override fun setVolume(level: Double) = commandPlayer("setVolume") { it.volume = level.toFloat() }
951
965
 
952
- override fun getVolume(): Double = runBlockingOnMain { player.volume.toDouble() }
966
+ override fun getVolume(): Double = readPlayer(1.0) { it.volume.toDouble() }
953
967
 
954
- override fun setRate(rate: Double) = runBlockingOnMain { player.playbackSpeed = rate.toFloat() }
968
+ override fun setRate(rate: Double) =
969
+ commandPlayer("setRate") { it.playbackSpeed = rate.toFloat() }
955
970
 
956
- override fun getRate(): Double = runBlockingOnMain { player.playbackSpeed.toDouble() }
971
+ override fun getRate(): Double = readPlayer(1.0) { it.playbackSpeed.toDouble() }
957
972
 
958
- override fun getProgress(): Progress = runBlockingOnMain {
959
- Progress(
960
- duration = player.duration.toSeconds(),
961
- position = player.position.toSeconds(),
962
- buffered = player.bufferedPosition.toSeconds(),
963
- )
964
- }
973
+ override fun getProgress(): Progress =
974
+ readPlayer(Progress(duration = 0.0, position = 0.0, buffered = 0.0)) { player ->
975
+ Progress(
976
+ duration = player.duration.toSeconds(),
977
+ position = player.position.toSeconds(),
978
+ buffered = player.bufferedPosition.toSeconds(),
979
+ )
980
+ }
965
981
 
966
- override fun getPlayback(): Playback = runBlockingOnMain { player.getPlayback() }
982
+ override fun getPlayback(): Playback =
983
+ readPlayer(Playback(PlaybackState.NONE, null)) { it.getPlayback() }
967
984
 
968
- override fun getPlayingState(): PlayingState = runBlockingOnMain { player.getPlayingState() }
985
+ override fun getPlayingState(): PlayingState =
986
+ readPlayer(PlayingState(playing = false, buffering = false)) { it.getPlayingState() }
969
987
 
970
988
  override fun getRepeatMode(): RepeatMode = runBlockingOnMain {
971
989
  connectedService?.player?.repeatMode ?: pendingRepeatMode ?: RepeatMode.OFF
@@ -976,121 +994,121 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
976
994
  connectedService?.player?.let { it.repeatMode = mode } ?: run { pendingRepeatMode = mode }
977
995
  }
978
996
 
979
- override fun getShuffleEnabled(): Boolean = runBlockingOnMain { player.shuffleMode }
997
+ override fun getShuffleEnabled(): Boolean = readPlayer(false) { it.shuffleMode }
980
998
 
981
- override fun setShuffleEnabled(enabled: Boolean) = runBlockingOnMain {
982
- player.shuffleMode = enabled
983
- }
999
+ override fun setShuffleEnabled(enabled: Boolean) =
1000
+ commandPlayer("setShuffleEnabled") { player -> player.shuffleMode = enabled }
984
1001
 
985
- override fun setPlaybackIntervalEnabled(enabled: Boolean) = runBlockingOnMain {
986
- player.setPlaybackIntervalEnabled(enabled)
987
- }
1002
+ override fun setPlaybackIntervalEnabled(enabled: Boolean) =
1003
+ commandPlayer("setPlaybackIntervalEnabled") { player ->
1004
+ player.setPlaybackIntervalEnabled(enabled)
1005
+ }
988
1006
 
989
- override fun getPlaybackError(): PlaybackError? = runBlockingOnMain { player.playbackError }
1007
+ override fun getPlaybackError(): PlaybackError? = readPlayer(null) { it.playbackError }
990
1008
 
991
- override fun retry() = runBlockingOnMain { player.prepare() }
1009
+ override fun retry() = commandPlayer("retry") { it.prepare() }
992
1010
 
993
1011
  // ============================================================================
994
1012
  // MARK: Queue Management
995
1013
  // ============================================================================
996
1014
 
997
- override fun add(tracks: Array<Track>, insertBeforeIndex: Double?) = runBlockingOnMain {
998
- val inputIndex = insertBeforeIndex?.toInt() ?: -1
999
- player.add(tracks, inputIndex)
1000
- }
1015
+ override fun add(tracks: Array<Track>, insertBeforeIndex: Double?) =
1016
+ commandPlayer("add") { player ->
1017
+ val inputIndex = insertBeforeIndex?.toInt() ?: -1
1018
+ player.add(tracks, inputIndex)
1019
+ }
1001
1020
 
1002
- override fun move(fromIndex: Double, toIndex: Double) = runBlockingOnMain {
1003
- player.move(fromIndex.toInt(), toIndex.toInt())
1004
- }
1021
+ override fun move(fromIndex: Double, toIndex: Double) =
1022
+ commandPlayer("move") { player -> player.move(fromIndex.toInt(), toIndex.toInt()) }
1005
1023
 
1006
- override fun remove(indexes: DoubleArray) = runBlockingOnMain {
1007
- val indexList = indexes.map { it.toInt() }
1008
- player.remove(indexList)
1009
- }
1024
+ override fun remove(indexes: DoubleArray) =
1025
+ commandPlayer("remove") { player ->
1026
+ val indexList = indexes.map { it.toInt() }
1027
+ player.remove(indexList)
1028
+ }
1010
1029
 
1011
- override fun removeUpcomingTracks() = runBlockingOnMain { player.removeUpcomingTracks() }
1030
+ override fun removeUpcomingTracks() =
1031
+ commandPlayer("removeUpcomingTracks") { it.removeUpcomingTracks() }
1012
1032
 
1013
- override fun skip(index: Double, initialPosition: Double?) = runBlockingOnMain {
1014
- player.skipTo(index.toInt())
1033
+ override fun skip(index: Double, initialPosition: Double?) =
1034
+ commandPlayer("skip") { player ->
1035
+ player.skipTo(index.toInt())
1015
1036
 
1016
- if (initialPosition != null && initialPosition >= 0) {
1017
- player.seekTo((initialPosition * 1000).toLong(), TimeUnit.MILLISECONDS)
1037
+ if (initialPosition != null && initialPosition >= 0) {
1038
+ player.seekTo((initialPosition * 1000).toLong(), TimeUnit.MILLISECONDS)
1039
+ }
1018
1040
  }
1019
- }
1020
1041
 
1021
- override fun skipToNext(initialPosition: Double?) = runBlockingOnMain {
1022
- player.next()
1042
+ override fun skipToNext(initialPosition: Double?) =
1043
+ commandPlayer("skipToNext") { player ->
1044
+ player.next()
1023
1045
 
1024
- if (initialPosition != null && initialPosition >= 0) {
1025
- player.seekTo((initialPosition * 1000).toLong(), TimeUnit.MILLISECONDS)
1046
+ if (initialPosition != null && initialPosition >= 0) {
1047
+ player.seekTo((initialPosition * 1000).toLong(), TimeUnit.MILLISECONDS)
1048
+ }
1026
1049
  }
1027
- }
1028
1050
 
1029
- override fun skipToPrevious(initialPosition: Double?) = runBlockingOnMain {
1030
- player.previous()
1051
+ override fun skipToPrevious(initialPosition: Double?) =
1052
+ commandPlayer("skipToPrevious") { player ->
1053
+ player.previous()
1031
1054
 
1032
- if (initialPosition != null && initialPosition >= 0) {
1033
- player.seekTo((initialPosition * 1000).toLong(), TimeUnit.MILLISECONDS)
1055
+ if (initialPosition != null && initialPosition >= 0) {
1056
+ player.seekTo((initialPosition * 1000).toLong(), TimeUnit.MILLISECONDS)
1057
+ }
1034
1058
  }
1035
- }
1036
1059
 
1037
1060
  override fun setQueue(tracks: Array<Track>, startIndex: Double?, startPosition: Double?) =
1038
- runBlockingOnMain {
1061
+ commandPlayer("setQueue") { player ->
1039
1062
  player.setQueue(tracks, startIndex?.toInt() ?: 0, ((startPosition ?: 0.0) * 1000).toLong())
1040
1063
  }
1041
1064
 
1042
- override fun setActiveTrackFavorited(favorited: Boolean): Unit = runBlockingOnMain {
1043
- // Applied-result is for MediaSession honesty; the JS API stays fire-and-forget.
1044
- player.setActiveTrackFavorited(favorited)
1045
- Unit
1046
- }
1065
+ override fun setActiveTrackFavorited(favorited: Boolean): Unit =
1066
+ commandPlayer("setActiveTrackFavorited") { player ->
1067
+ // Applied-result is for MediaSession honesty; the JS API stays fire-and-forget.
1068
+ player.setActiveTrackFavorited(favorited)
1069
+ }
1047
1070
 
1048
- override fun toggleActiveTrackFavorited(): Unit = runBlockingOnMain {
1049
- player.toggleActiveTrackFavorited()
1050
- Unit
1051
- }
1071
+ override fun toggleActiveTrackFavorited(): Unit =
1072
+ commandPlayer("toggleActiveTrackFavorited") { it.toggleActiveTrackFavorited() }
1052
1073
 
1053
- override fun getQueue(): Array<Track> = runBlockingOnMain { player.tracks }
1074
+ override fun getQueue(): Array<Track> = readPlayer(emptyArray()) { it.tracks }
1054
1075
 
1055
- override fun getTrack(index: Double): Track? = runBlockingOnMain {
1056
- try {
1057
- player.getTrack(index.toInt())
1058
- } catch (e: IllegalArgumentException) {
1059
- null
1076
+ override fun getTrack(index: Double): Track? =
1077
+ readPlayer(null) { player ->
1078
+ try {
1079
+ player.getTrack(index.toInt())
1080
+ } catch (e: IllegalArgumentException) {
1081
+ null
1082
+ }
1060
1083
  }
1061
- }
1062
1084
 
1063
- override fun getActiveTrackIndex(): Double? = runBlockingOnMain {
1064
- player.currentIndex?.toDouble()
1065
- }
1085
+ override fun getActiveTrackIndex(): Double? = readPlayer(null) { it.currentIndex?.toDouble() }
1066
1086
 
1067
- override fun getActiveTrack(): Track? = runBlockingOnMain { player.currentTrack }
1087
+ override fun getActiveTrack(): Track? = readPlayer(null) { it.currentTrack }
1068
1088
 
1069
1089
  // ============================================================================
1070
1090
  // MARK: Now Playing Metadata
1071
1091
  // ============================================================================
1072
1092
 
1073
- override fun updateNowPlaying(update: NowPlayingUpdate?) = runBlockingOnMain {
1074
- player.nowPlaying.updateNowPlaying(update)
1075
- }
1093
+ override fun updateNowPlaying(update: NowPlayingUpdate?) =
1094
+ commandPlayer("updateNowPlaying") { player -> player.nowPlaying.updateNowPlaying(update) }
1076
1095
 
1077
- override fun flashNowPlaying(update: NowPlayingUpdate, durationMs: Double) = runBlockingOnMain {
1078
- player.nowPlaying.flashNowPlaying(update, durationMs)
1079
- }
1096
+ override fun flashNowPlaying(update: NowPlayingUpdate, durationMs: Double) =
1097
+ commandPlayer("flashNowPlaying") { player ->
1098
+ player.nowPlaying.flashNowPlaying(update, durationMs)
1099
+ }
1080
1100
 
1081
- override fun clearNowPlayingFlash() = runBlockingOnMain {
1082
- player.nowPlaying.clearNowPlayingFlash()
1083
- }
1101
+ override fun clearNowPlayingFlash() =
1102
+ commandPlayer("clearNowPlayingFlash") { player -> player.nowPlaying.clearNowPlayingFlash() }
1084
1103
 
1085
- override fun getNowPlaying(): NowPlayingMetadata? = runBlockingOnMain {
1086
- player.nowPlaying.getNowPlaying()
1087
- }
1104
+ override fun getNowPlaying(): NowPlayingMetadata? =
1105
+ readPlayer(null) { player -> player.nowPlaying.getNowPlaying() }
1088
1106
 
1089
1107
  // ============================================================================
1090
1108
  // MARK: Network Connectivity
1091
1109
  // ============================================================================
1092
1110
 
1093
- override fun getOnline(): Boolean = runBlockingOnMain { player.getOnline() }
1111
+ override fun getOnline(): Boolean = readPlayer(true) { it.getOnline() }
1094
1112
 
1095
1113
  // ============================================================================
1096
1114
  // MARK: System Volume
@@ -1116,35 +1134,32 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
1116
1134
  // MARK: Equalizer (Android only)
1117
1135
  // ============================================================================
1118
1136
 
1119
- override fun getEqualizerSettings(): EqualizerSettings? = runBlockingOnMain {
1120
- player.equalizer.getSettings()
1121
- }
1137
+ override fun getEqualizerSettings(): EqualizerSettings? =
1138
+ readPlayer(null) { player -> player.equalizer.getSettings() }
1122
1139
 
1123
- override fun setEqualizerEnabled(enabled: Boolean) = runBlockingOnMain {
1124
- player.equalizer.setEnabled(enabled)
1125
- }
1140
+ override fun setEqualizerEnabled(enabled: Boolean) =
1141
+ commandPlayer("setEqualizerEnabled") { player -> player.equalizer.setEnabled(enabled) }
1126
1142
 
1127
- override fun setEqualizerPreset(preset: String) = runBlockingOnMain {
1128
- player.equalizer.setPreset(preset)
1129
- }
1143
+ override fun setEqualizerPreset(preset: String) =
1144
+ commandPlayer("setEqualizerPreset") { player -> player.equalizer.setPreset(preset) }
1130
1145
 
1131
- override fun setEqualizerLevels(levels: DoubleArray) = runBlockingOnMain {
1132
- player.equalizer.setLevels(levels)
1133
- }
1146
+ override fun setEqualizerLevels(levels: DoubleArray) =
1147
+ commandPlayer("setEqualizerLevels") { player -> player.equalizer.setLevels(levels) }
1134
1148
 
1135
1149
  // ============================================================================
1136
1150
  // MARK: Sleep Timer
1137
1151
  // ============================================================================
1138
1152
 
1139
- override fun getSleepTimer(): SleepTimer = runBlockingOnMain { player.sleepTimer.get() }
1153
+ override fun getSleepTimer(): SleepTimer =
1154
+ readPlayer(SleepTimer.create(NullType.NULL)) { it.sleepTimer.get() }
1140
1155
 
1141
- override fun setSleepTimer(seconds: Double, fadeDuration: Double?) = runBlockingOnMain {
1142
- player.sleepTimer.setAfter(seconds, fadeDuration)
1143
- }
1156
+ override fun setSleepTimer(seconds: Double, fadeDuration: Double?) =
1157
+ commandPlayer("setSleepTimer") { player -> player.sleepTimer.setAfter(seconds, fadeDuration) }
1144
1158
 
1145
- override fun setSleepTimerToEndOfTrack() = runBlockingOnMain { player.sleepTimer.setEndOfTrack() }
1159
+ override fun setSleepTimerToEndOfTrack() =
1160
+ commandPlayer("setSleepTimerToEndOfTrack") { it.sleepTimer.setEndOfTrack() }
1146
1161
 
1147
- override fun clearSleepTimer(): Boolean = runBlockingOnMain { player.sleepTimer.clear() }
1162
+ override fun clearSleepTimer(): Boolean = readPlayer(false) { it.sleepTimer.clear() }
1148
1163
 
1149
1164
  // ============================================================================
1150
1165
  // MARK: Battery Optimization (Android only)
@@ -1285,6 +1300,29 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
1285
1300
  private val service: Service
1286
1301
  get() = connectedService ?: throw Exception("Player not initialized")
1287
1302
 
1303
+ /**
1304
+ * The player while its service is connected: not before setupPlayer, nor while the service
1305
+ * restarts.
1306
+ */
1307
+ private val connectedPlayer: Player?
1308
+ get() = connectedService?.player
1309
+
1310
+ /** What [read] gets from the player, or without one [fallback], the answer iOS gives then. */
1311
+ private fun <T> readPlayer(fallback: T, read: suspend (Player) -> T): T = runBlockingOnMain {
1312
+ val player = connectedPlayer ?: return@runBlockingOnMain fallback
1313
+ read(player)
1314
+ }
1315
+
1316
+ /** Runs [command] on the player; without one it is dropped with a warning, as iOS drops it. */
1317
+ private fun commandPlayer(name: String, command: suspend (Player) -> Unit) = runBlockingOnMain {
1318
+ val player = connectedPlayer
1319
+ if (player == null) {
1320
+ Timber.w("$name before the player is set up, or while its service restarts: ignored")
1321
+ } else {
1322
+ command(player)
1323
+ }
1324
+ }
1325
+
1288
1326
  internal val player
1289
1327
  get() = service.player
1290
1328
 
@@ -2,6 +2,7 @@ package com.audiobrowser.util
2
2
 
3
3
  import android.net.Uri
4
4
  import androidx.core.net.toUri
5
+ import com.margelo.nitro.audiobrowser.NavigationErrorKind
5
6
  import java.net.URLEncoder
6
7
 
7
8
  /**
@@ -49,6 +50,11 @@ object BrowserPathHelper {
49
50
  // Query parameter name for the tapped child's page position (tie-breaker)
50
51
  private const val CONTEXTUAL_INDEX_PARAM = "__index"
51
52
 
53
+ /** Whether a navigation error on this path came from a browse or a search */
54
+ fun navigationErrorKind(path: String): NavigationErrorKind =
55
+ if (path.startsWith("$SEARCH_PATH_PREFIX?")) NavigationErrorKind.SEARCH
56
+ else NavigationErrorKind.BROWSE
57
+
52
58
  /** Check if a path is a special system path (not a regular navigation path) */
53
59
  fun isSpecialPath(path: String): Boolean {
54
60
  return path == ROOT_PATH || path.startsWith("$SEARCH_PATH_PREFIX?")
@@ -1,5 +1,6 @@
1
1
  package com.audiobrowser.util
2
2
 
3
+ import com.margelo.nitro.audiobrowser.NavigationErrorKind
3
4
  import org.junit.Assert.assertEquals
4
5
  import org.junit.Assert.assertNull
5
6
  import org.junit.Test
@@ -50,4 +51,17 @@ class BrowserPathHelperTest {
50
51
  assertNull(BrowserPathHelper.extractIndex("/library?__trackId=song.mp3&__index=x"))
51
52
  assertNull(BrowserPathHelper.extractIndex("/library?__trackId=song.mp3&__index=-1"))
52
53
  }
54
+
55
+ @Test
56
+ fun `a search path is a search, anything else a browse`() {
57
+ assertEquals(
58
+ NavigationErrorKind.SEARCH,
59
+ BrowserPathHelper.navigationErrorKind(BrowserPathHelper.createSearchPath("jazz")),
60
+ )
61
+ assertEquals(
62
+ NavigationErrorKind.BROWSE,
63
+ BrowserPathHelper.navigationErrorKind("/search?q=jazz"),
64
+ )
65
+ assertEquals(NavigationErrorKind.BROWSE, BrowserPathHelper.navigationErrorKind("/__searchable"))
66
+ }
53
67
  }
@@ -44,8 +44,12 @@ enum BrowserPathHelper {
44
44
 
45
45
  /// Check if a path is a special system path (not a regular navigation path)
46
46
  static func isSpecialPath(_ path: String) -> Bool {
47
- path == rootPath ||
48
- path.hasPrefix("\(searchPathPrefix)?")
47
+ path == rootPath || isSearchPath(path)
48
+ }
49
+
50
+ /// Check if a path is a search path (`/__search?q=…`)
51
+ static func isSearchPath(_ path: String) -> Bool {
52
+ path.hasPrefix("\(searchPathPrefix)?")
49
53
  }
50
54
 
51
55
  /// Create a search path for a given query
@@ -784,6 +784,7 @@ public final class RNABCarPlayController: NSObject {
784
784
  guard let formatter = config.formatNavigationError else { return fallback }
785
785
  let params = FormatNavigationErrorParams(
786
786
  error: navError, defaultFormatted: fallback, path: path,
787
+ kind: NavigationErrorKind(path: path),
787
788
  )
788
789
  do {
789
790
  let custom = try await formatter(params).await()
@@ -1317,7 +1318,10 @@ public final class RNABCarPlayController: NSObject {
1317
1318
  if let formatter = config.formatNavigationError {
1318
1319
  logger.debug("Calling formatNavigationError callback...")
1319
1320
  // Call the JS callback and handle result
1320
- let params = FormatNavigationErrorParams(error: error, defaultFormatted: defaultFormatted, path: path)
1321
+ let params = FormatNavigationErrorParams(
1322
+ error: error, defaultFormatted: defaultFormatted, path: path,
1323
+ kind: NavigationErrorKind(path: path),
1324
+ )
1321
1325
  // The result callbacks are @Sendable and hop back explicitly: Nitro resolves
1322
1326
  // its promises synchronously on the JS thread, so a plain closure would
1323
1327
  // inherit this type's MainActor isolation and trap on entry under Swift 6's
@@ -54,3 +54,10 @@ extension NavigationError {
54
54
  return FormattedNavigationError(title: title, message: message.isEmpty ? nil : message)
55
55
  }
56
56
  }
57
+
58
+ extension NavigationErrorKind {
59
+ /// The kind of request a navigation error on `path` came from.
60
+ init(path: String) {
61
+ self = BrowserPathHelper.isSearchPath(path) ? .search : .browse
62
+ }
63
+ }
@@ -465,7 +465,10 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
465
465
  // Format the error (async if using JS callback, sync for defaults)
466
466
  let defaultFormatted = navError.defaultFormatted()
467
467
  if let formatter = onMainActor({ browserManager.config.formatNavigationError }) {
468
- let params = FormatNavigationErrorParams(error: navError, defaultFormatted: defaultFormatted, path: path)
468
+ let params = FormatNavigationErrorParams(
469
+ error: navError, defaultFormatted: defaultFormatted, path: path,
470
+ kind: NavigationErrorKind(path: path),
471
+ )
469
472
  // Dispatch to main thread for the Nitro bridge call to avoid C++ noexcept crashes.
470
473
  // The result callbacks are @Sendable: a plain closure would inherit MainActor
471
474
  // isolation from this block, and Nitro resolves its promises synchronously on the
@@ -166,3 +166,14 @@ import Testing
166
166
  @Test func isContextualReturnsTrueWithAmpersandSeparator() {
167
167
  #expect(BrowserPathHelper.isContextual("/lib?q=1&__trackId=x") == true)
168
168
  }
169
+
170
+ // MARK: - isSearchPath
171
+
172
+ @Test func isSearchPathMatchesCreatedSearchPaths() {
173
+ #expect(BrowserPathHelper.isSearchPath(BrowserPathHelper.createSearchPath("jazz")) == true)
174
+ }
175
+
176
+ @Test func isSearchPathRejectsBrowsePaths() {
177
+ #expect(BrowserPathHelper.isSearchPath("/search?q=jazz") == false)
178
+ #expect(BrowserPathHelper.isSearchPath("/__searchable") == false)
179
+ }
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.NavigationErrorManager = void 0;
7
+ var _BrowserPathHelper = require("../util/BrowserPathHelper");
7
8
  const ERROR_TITLES = {
8
9
  'network-error': 'Network Error',
9
10
  'http-error': 'Server Error',
@@ -77,7 +78,8 @@ class NavigationErrorManager {
77
78
  const customFormatted = this.formatCallback({
78
79
  error: navError,
79
80
  defaultFormatted,
80
- path
81
+ path,
82
+ kind: _BrowserPathHelper.BrowserPathHelper.navigationErrorKind(path)
81
83
  });
82
84
  this._formattedNavigationError = customFormatted || defaultFormatted;
83
85
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"names":["ERROR_TITLES","NavigationErrorManager","onNavigationError","onFormattedNavigationError","setFormatCallback","callback","formatCallback","clearNavigationError","_navigationError","undefined","_formattedNavigationError","error","setNavigationError","code","message","path","statusCode","navError","statusCodeSuccess","defaultFormatted","title","customFormatted","console","getNavigationError","getFormattedNavigationError","exports"],"sourceRoot":"../../../../src","sources":["web/browser/NavigationErrorManager.ts"],"mappings":";;;;;;AAQA,MAAMA,YAAiD,GAAG;EACxD,eAAe,EAAE,eAAe;EAChC,YAAY,EAAE,cAAc;EAC5B,mBAAmB,EAAE,mBAAmB;EACxC,gBAAgB,EAAE,OAAO;EACzB,eAAe,EAAE,OAAO;EACxB,eAAe,EAAE,cAAc;EAC/B,SAAS,EAAE;AACb,CAAC;;AAED;AACA;AACA;AACA;AACO,MAAMC,sBAAsB,CAAC;EAKlC;EACAC,iBAAiB,GAAyCA,CAAA,KAAM,CAAC,CAAC;EAClEC,0BAA0B,GAEdA,CAAA,KAAM,CAAC,CAAC;;EAEpB;AACF;AACA;EACEC,iBAAiBA,CACfC,QAA6D,EACvD;IACN,IAAI,CAACC,cAAc,GAAGD,QAAQ;EAChC;;EAEA;AACF;AACA;EACEE,oBAAoBA,CAAA,EAAS;IAC3B,IACE,IAAI,CAACC,gBAAgB,KAAKC,SAAS,IACnC,IAAI,CAACC,yBAAyB,KAAKD,SAAS,EAC5C;MACA,IAAI,CAACD,gBAAgB,GAAGC,SAAS;MACjC,IAAI,CAACC,yBAAyB,GAAGD,SAAS;MAC1C,IAAI,CAACP,iBAAiB,CAAC;QAAES,KAAK,EAAEF;MAAU,CAAC,CAAC;MAC5C,IAAI,CAACN,0BAA0B,CAACM,SAAS,CAAC;IAC5C;EACF;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEG,kBAAkBA,CAChBC,IAAyB,EACzBC,OAAe,EACfC,IAAa,EACbC,UAAmB,EACb;IACN,MAAMC,QAAyB,GAAG;MAChCJ,IAAI;MACJC,OAAO;MACPE,UAAU;MACVE,iBAAiB,EAAET;IACrB,CAAC;IACD,IAAI,CAACD,gBAAgB,GAAGS,QAAQ;IAChC,IAAI,CAACf,iBAAiB,CAAC;MAAES,KAAK,EAAEM;IAAS,CAAC,CAAC;;IAE3C;IACA,MAAME,gBAA0C,GAAG;MACjDC,KAAK,EAAEpB,YAAY,CAACa,IAAI,CAAC;MACzBC;IACF,CAAC;;IAED;IACA,IAAI,IAAI,CAACR,cAAc,IAAIS,IAAI,EAAE;MAC/B,IAAI;QACF,MAAMM,eAAe,GAAG,IAAI,CAACf,cAAc,CAAC;UAC1CK,KAAK,EAAEM,QAAQ;UACfE,gBAAgB;UAChBJ;QACF,CAAC,CAAC;QACF,IAAI,CAACL,yBAAyB,GAAGW,eAAe,IAAIF,gBAAgB;MACtE,CAAC,CAAC,OAAOR,KAAK,EAAE;QACdW,OAAO,CAACX,KAAK,CAAC,0CAA0C,EAAEA,KAAK,CAAC;QAChE,IAAI,CAACD,yBAAyB,GAAGS,gBAAgB;MACnD;IACF,CAAC,MAAM;MACL,IAAI,CAACT,yBAAyB,GAAGS,gBAAgB;IACnD;IAEA,IAAI,CAAChB,0BAA0B,CAAC,IAAI,CAACO,yBAAyB,CAAC;EACjE;;EAEA;AACF;AACA;EACEa,kBAAkBA,CAAA,EAAgC;IAChD,OAAO,IAAI,CAACf,gBAAgB;EAC9B;;EAEA;AACF;AACA;EACEgB,2BAA2BA,CAAA,EAAyC;IAClE,OAAO,IAAI,CAACd,yBAAyB;EACvC;AACF;AAACe,OAAA,CAAAxB,sBAAA,GAAAA,sBAAA","ignoreList":[]}
1
+ {"version":3,"names":["_BrowserPathHelper","require","ERROR_TITLES","NavigationErrorManager","onNavigationError","onFormattedNavigationError","setFormatCallback","callback","formatCallback","clearNavigationError","_navigationError","undefined","_formattedNavigationError","error","setNavigationError","code","message","path","statusCode","navError","statusCodeSuccess","defaultFormatted","title","customFormatted","kind","BrowserPathHelper","navigationErrorKind","console","getNavigationError","getFormattedNavigationError","exports"],"sourceRoot":"../../../../src","sources":["web/browser/NavigationErrorManager.ts"],"mappings":";;;;;;AAOA,IAAAA,kBAAA,GAAAC,OAAA;AAEA,MAAMC,YAAiD,GAAG;EACxD,eAAe,EAAE,eAAe;EAChC,YAAY,EAAE,cAAc;EAC5B,mBAAmB,EAAE,mBAAmB;EACxC,gBAAgB,EAAE,OAAO;EACzB,eAAe,EAAE,OAAO;EACxB,eAAe,EAAE,cAAc;EAC/B,SAAS,EAAE;AACb,CAAC;;AAED;AACA;AACA;AACA;AACO,MAAMC,sBAAsB,CAAC;EAKlC;EACAC,iBAAiB,GAAyCA,CAAA,KAAM,CAAC,CAAC;EAClEC,0BAA0B,GAEdA,CAAA,KAAM,CAAC,CAAC;;EAEpB;AACF;AACA;EACEC,iBAAiBA,CACfC,QAA6D,EACvD;IACN,IAAI,CAACC,cAAc,GAAGD,QAAQ;EAChC;;EAEA;AACF;AACA;EACEE,oBAAoBA,CAAA,EAAS;IAC3B,IACE,IAAI,CAACC,gBAAgB,KAAKC,SAAS,IACnC,IAAI,CAACC,yBAAyB,KAAKD,SAAS,EAC5C;MACA,IAAI,CAACD,gBAAgB,GAAGC,SAAS;MACjC,IAAI,CAACC,yBAAyB,GAAGD,SAAS;MAC1C,IAAI,CAACP,iBAAiB,CAAC;QAAES,KAAK,EAAEF;MAAU,CAAC,CAAC;MAC5C,IAAI,CAACN,0BAA0B,CAACM,SAAS,CAAC;IAC5C;EACF;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEG,kBAAkBA,CAChBC,IAAyB,EACzBC,OAAe,EACfC,IAAa,EACbC,UAAmB,EACb;IACN,MAAMC,QAAyB,GAAG;MAChCJ,IAAI;MACJC,OAAO;MACPE,UAAU;MACVE,iBAAiB,EAAET;IACrB,CAAC;IACD,IAAI,CAACD,gBAAgB,GAAGS,QAAQ;IAChC,IAAI,CAACf,iBAAiB,CAAC;MAAES,KAAK,EAAEM;IAAS,CAAC,CAAC;;IAE3C;IACA,MAAME,gBAA0C,GAAG;MACjDC,KAAK,EAAEpB,YAAY,CAACa,IAAI,CAAC;MACzBC;IACF,CAAC;;IAED;IACA,IAAI,IAAI,CAACR,cAAc,IAAIS,IAAI,EAAE;MAC/B,IAAI;QACF,MAAMM,eAAe,GAAG,IAAI,CAACf,cAAc,CAAC;UAC1CK,KAAK,EAAEM,QAAQ;UACfE,gBAAgB;UAChBJ,IAAI;UACJO,IAAI,EAAEC,oCAAiB,CAACC,mBAAmB,CAACT,IAAI;QAClD,CAAC,CAAC;QACF,IAAI,CAACL,yBAAyB,GAAGW,eAAe,IAAIF,gBAAgB;MACtE,CAAC,CAAC,OAAOR,KAAK,EAAE;QACdc,OAAO,CAACd,KAAK,CAAC,0CAA0C,EAAEA,KAAK,CAAC;QAChE,IAAI,CAACD,yBAAyB,GAAGS,gBAAgB;MACnD;IACF,CAAC,MAAM;MACL,IAAI,CAACT,yBAAyB,GAAGS,gBAAgB;IACnD;IAEA,IAAI,CAAChB,0BAA0B,CAAC,IAAI,CAACO,yBAAyB,CAAC;EACjE;;EAEA;AACF;AACA;EACEgB,kBAAkBA,CAAA,EAAgC;IAChD,OAAO,IAAI,CAAClB,gBAAgB;EAC9B;;EAEA;AACF;AACA;EACEmB,2BAA2BA,CAAA,EAAyC;IAClE,OAAO,IAAI,CAACjB,yBAAyB;EACvC;AACF;AAACkB,OAAA,CAAA3B,sBAAA,GAAAA,sBAAA","ignoreList":[]}
@@ -31,6 +31,12 @@ const BrowserPathHelper = exports.BrowserPathHelper = {
31
31
  CONTEXTUAL_TRACK_PARAM: '__trackId',
32
32
  /** Query parameter name for the tapped child's page position (tie-breaker) */
33
33
  CONTEXTUAL_INDEX_PARAM: '__index',
34
+ /**
35
+ * Whether a navigation error on this path came from a browse or a search
36
+ */
37
+ navigationErrorKind(path) {
38
+ return path.startsWith(`${this.SEARCH_PATH_PREFIX}?`) ? 'search' : 'browse';
39
+ },
34
40
  /**
35
41
  * Create a search path for a given query
36
42
  */
@@ -1 +1 @@
1
- {"version":3,"names":["BrowserPathHelper","exports","SEARCH_PATH_PREFIX","CONTEXTUAL_TRACK_PARAM","CONTEXTUAL_INDEX_PARAM","createSearchPath","query","encodedQuery","encodeURIComponent","isContextual","path","includes","stripTrackId","url","isFullUrl","startsWith","urlObj","URL","undefined","searchParams","delete","toString","search","pathname","paramPattern","RegExp","result","replace","build","parentPath","trackId","index","separator","indexParam","extractTrackId","extractParam","extractIndex","raw","test","Number","parseInt","param","get","match","decodeURIComponent","buildUrl","baseUrl","normalizedBase","normalizedPath"],"sourceRoot":"../../../../src","sources":["web/util/BrowserPathHelper.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["BrowserPathHelper","exports","SEARCH_PATH_PREFIX","CONTEXTUAL_TRACK_PARAM","CONTEXTUAL_INDEX_PARAM","navigationErrorKind","path","startsWith","createSearchPath","query","encodedQuery","encodeURIComponent","isContextual","includes","stripTrackId","url","isFullUrl","urlObj","URL","undefined","searchParams","delete","toString","search","pathname","paramPattern","RegExp","result","replace","build","parentPath","trackId","index","separator","indexParam","extractTrackId","extractParam","extractIndex","raw","test","Number","parseInt","param","get","match","decodeURIComponent","buildUrl","baseUrl","normalizedBase","normalizedPath"],"sourceRoot":"../../../../src","sources":["web/util/BrowserPathHelper.ts"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
+ import { BrowserPathHelper } from '../util/BrowserPathHelper';
3
4
  const ERROR_TITLES = {
4
5
  'network-error': 'Network Error',
5
6
  'http-error': 'Server Error',
@@ -73,7 +74,8 @@ export class NavigationErrorManager {
73
74
  const customFormatted = this.formatCallback({
74
75
  error: navError,
75
76
  defaultFormatted,
76
- path
77
+ path,
78
+ kind: BrowserPathHelper.navigationErrorKind(path)
77
79
  });
78
80
  this._formattedNavigationError = customFormatted || defaultFormatted;
79
81
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"names":["ERROR_TITLES","NavigationErrorManager","onNavigationError","onFormattedNavigationError","setFormatCallback","callback","formatCallback","clearNavigationError","_navigationError","undefined","_formattedNavigationError","error","setNavigationError","code","message","path","statusCode","navError","statusCodeSuccess","defaultFormatted","title","customFormatted","console","getNavigationError","getFormattedNavigationError"],"sourceRoot":"../../../../src","sources":["web/browser/NavigationErrorManager.ts"],"mappings":";;AAQA,MAAMA,YAAiD,GAAG;EACxD,eAAe,EAAE,eAAe;EAChC,YAAY,EAAE,cAAc;EAC5B,mBAAmB,EAAE,mBAAmB;EACxC,gBAAgB,EAAE,OAAO;EACzB,eAAe,EAAE,OAAO;EACxB,eAAe,EAAE,cAAc;EAC/B,SAAS,EAAE;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,MAAMC,sBAAsB,CAAC;EAKlC;EACAC,iBAAiB,GAAyCA,CAAA,KAAM,CAAC,CAAC;EAClEC,0BAA0B,GAEdA,CAAA,KAAM,CAAC,CAAC;;EAEpB;AACF;AACA;EACEC,iBAAiBA,CACfC,QAA6D,EACvD;IACN,IAAI,CAACC,cAAc,GAAGD,QAAQ;EAChC;;EAEA;AACF;AACA;EACEE,oBAAoBA,CAAA,EAAS;IAC3B,IACE,IAAI,CAACC,gBAAgB,KAAKC,SAAS,IACnC,IAAI,CAACC,yBAAyB,KAAKD,SAAS,EAC5C;MACA,IAAI,CAACD,gBAAgB,GAAGC,SAAS;MACjC,IAAI,CAACC,yBAAyB,GAAGD,SAAS;MAC1C,IAAI,CAACP,iBAAiB,CAAC;QAAES,KAAK,EAAEF;MAAU,CAAC,CAAC;MAC5C,IAAI,CAACN,0BAA0B,CAACM,SAAS,CAAC;IAC5C;EACF;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEG,kBAAkBA,CAChBC,IAAyB,EACzBC,OAAe,EACfC,IAAa,EACbC,UAAmB,EACb;IACN,MAAMC,QAAyB,GAAG;MAChCJ,IAAI;MACJC,OAAO;MACPE,UAAU;MACVE,iBAAiB,EAAET;IACrB,CAAC;IACD,IAAI,CAACD,gBAAgB,GAAGS,QAAQ;IAChC,IAAI,CAACf,iBAAiB,CAAC;MAAES,KAAK,EAAEM;IAAS,CAAC,CAAC;;IAE3C;IACA,MAAME,gBAA0C,GAAG;MACjDC,KAAK,EAAEpB,YAAY,CAACa,IAAI,CAAC;MACzBC;IACF,CAAC;;IAED;IACA,IAAI,IAAI,CAACR,cAAc,IAAIS,IAAI,EAAE;MAC/B,IAAI;QACF,MAAMM,eAAe,GAAG,IAAI,CAACf,cAAc,CAAC;UAC1CK,KAAK,EAAEM,QAAQ;UACfE,gBAAgB;UAChBJ;QACF,CAAC,CAAC;QACF,IAAI,CAACL,yBAAyB,GAAGW,eAAe,IAAIF,gBAAgB;MACtE,CAAC,CAAC,OAAOR,KAAK,EAAE;QACdW,OAAO,CAACX,KAAK,CAAC,0CAA0C,EAAEA,KAAK,CAAC;QAChE,IAAI,CAACD,yBAAyB,GAAGS,gBAAgB;MACnD;IACF,CAAC,MAAM;MACL,IAAI,CAACT,yBAAyB,GAAGS,gBAAgB;IACnD;IAEA,IAAI,CAAChB,0BAA0B,CAAC,IAAI,CAACO,yBAAyB,CAAC;EACjE;;EAEA;AACF;AACA;EACEa,kBAAkBA,CAAA,EAAgC;IAChD,OAAO,IAAI,CAACf,gBAAgB;EAC9B;;EAEA;AACF;AACA;EACEgB,2BAA2BA,CAAA,EAAyC;IAClE,OAAO,IAAI,CAACd,yBAAyB;EACvC;AACF","ignoreList":[]}
1
+ {"version":3,"names":["BrowserPathHelper","ERROR_TITLES","NavigationErrorManager","onNavigationError","onFormattedNavigationError","setFormatCallback","callback","formatCallback","clearNavigationError","_navigationError","undefined","_formattedNavigationError","error","setNavigationError","code","message","path","statusCode","navError","statusCodeSuccess","defaultFormatted","title","customFormatted","kind","navigationErrorKind","console","getNavigationError","getFormattedNavigationError"],"sourceRoot":"../../../../src","sources":["web/browser/NavigationErrorManager.ts"],"mappings":";;AAOA,SAASA,iBAAiB,QAAQ,2BAA2B;AAE7D,MAAMC,YAAiD,GAAG;EACxD,eAAe,EAAE,eAAe;EAChC,YAAY,EAAE,cAAc;EAC5B,mBAAmB,EAAE,mBAAmB;EACxC,gBAAgB,EAAE,OAAO;EACzB,eAAe,EAAE,OAAO;EACxB,eAAe,EAAE,cAAc;EAC/B,SAAS,EAAE;AACb,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,MAAMC,sBAAsB,CAAC;EAKlC;EACAC,iBAAiB,GAAyCA,CAAA,KAAM,CAAC,CAAC;EAClEC,0BAA0B,GAEdA,CAAA,KAAM,CAAC,CAAC;;EAEpB;AACF;AACA;EACEC,iBAAiBA,CACfC,QAA6D,EACvD;IACN,IAAI,CAACC,cAAc,GAAGD,QAAQ;EAChC;;EAEA;AACF;AACA;EACEE,oBAAoBA,CAAA,EAAS;IAC3B,IACE,IAAI,CAACC,gBAAgB,KAAKC,SAAS,IACnC,IAAI,CAACC,yBAAyB,KAAKD,SAAS,EAC5C;MACA,IAAI,CAACD,gBAAgB,GAAGC,SAAS;MACjC,IAAI,CAACC,yBAAyB,GAAGD,SAAS;MAC1C,IAAI,CAACP,iBAAiB,CAAC;QAAES,KAAK,EAAEF;MAAU,CAAC,CAAC;MAC5C,IAAI,CAACN,0BAA0B,CAACM,SAAS,CAAC;IAC5C;EACF;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEG,kBAAkBA,CAChBC,IAAyB,EACzBC,OAAe,EACfC,IAAa,EACbC,UAAmB,EACb;IACN,MAAMC,QAAyB,GAAG;MAChCJ,IAAI;MACJC,OAAO;MACPE,UAAU;MACVE,iBAAiB,EAAET;IACrB,CAAC;IACD,IAAI,CAACD,gBAAgB,GAAGS,QAAQ;IAChC,IAAI,CAACf,iBAAiB,CAAC;MAAES,KAAK,EAAEM;IAAS,CAAC,CAAC;;IAE3C;IACA,MAAME,gBAA0C,GAAG;MACjDC,KAAK,EAAEpB,YAAY,CAACa,IAAI,CAAC;MACzBC;IACF,CAAC;;IAED;IACA,IAAI,IAAI,CAACR,cAAc,IAAIS,IAAI,EAAE;MAC/B,IAAI;QACF,MAAMM,eAAe,GAAG,IAAI,CAACf,cAAc,CAAC;UAC1CK,KAAK,EAAEM,QAAQ;UACfE,gBAAgB;UAChBJ,IAAI;UACJO,IAAI,EAAEvB,iBAAiB,CAACwB,mBAAmB,CAACR,IAAI;QAClD,CAAC,CAAC;QACF,IAAI,CAACL,yBAAyB,GAAGW,eAAe,IAAIF,gBAAgB;MACtE,CAAC,CAAC,OAAOR,KAAK,EAAE;QACda,OAAO,CAACb,KAAK,CAAC,0CAA0C,EAAEA,KAAK,CAAC;QAChE,IAAI,CAACD,yBAAyB,GAAGS,gBAAgB;MACnD;IACF,CAAC,MAAM;MACL,IAAI,CAACT,yBAAyB,GAAGS,gBAAgB;IACnD;IAEA,IAAI,CAAChB,0BAA0B,CAAC,IAAI,CAACO,yBAAyB,CAAC;EACjE;;EAEA;AACF;AACA;EACEe,kBAAkBA,CAAA,EAAgC;IAChD,OAAO,IAAI,CAACjB,gBAAgB;EAC9B;;EAEA;AACF;AACA;EACEkB,2BAA2BA,CAAA,EAAyC;IAClE,OAAO,IAAI,CAAChB,yBAAyB;EACvC;AACF","ignoreList":[]}