diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 395ded94f..c3eee5125 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -270,7 +270,7 @@ class MainFragment : when (action) { is MainNavigationAction.Expand -> tryExpandSheets() is MainNavigationAction.Collapse -> tryCollapseSheets() - is MainNavigationAction.Directions -> findNavController().navigate(action.directions) + is MainNavigationAction.Directions -> findNavController().navigateSafe(action.directions) } navModel.mainNavigationAction.consume() diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt index 9267184a1..17a59ae2a 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -209,7 +209,7 @@ class AlbumDetailFragment : } else { logD("Navigating to another album") findNavController() - .navigate(AlbumDetailFragmentDirections.actionShowAlbum(item.album.uid)) + .navigateSafe(AlbumDetailFragmentDirections.actionShowAlbum(item.album.uid)) } } @@ -223,7 +223,7 @@ class AlbumDetailFragment : } else { logD("Navigating to another album") findNavController() - .navigate(AlbumDetailFragmentDirections.actionShowAlbum(item.uid)) + .navigateSafe(AlbumDetailFragmentDirections.actionShowAlbum(item.uid)) } } @@ -231,7 +231,7 @@ class AlbumDetailFragment : is Artist -> { logD("Navigating to another artist") findNavController() - .navigate(AlbumDetailFragmentDirections.actionShowArtist(item.uid)) + .navigateSafe(AlbumDetailFragmentDirections.actionShowArtist(item.uid)) } null -> {} else -> error("Unexpected datatype: ${item::class.java}") diff --git a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt index ea012162c..140ced37a 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -42,11 +42,7 @@ import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.NavigationViewModel -import org.oxycblt.auxio.util.collect -import org.oxycblt.auxio.util.collectImmediately -import org.oxycblt.auxio.util.logD -import org.oxycblt.auxio.util.showToast -import org.oxycblt.auxio.util.unlikelyToBeNull +import org.oxycblt.auxio.util.* /** * A [ListFragment] that shows information about an [Artist]. @@ -225,14 +221,14 @@ class ArtistDetailFragment : is Song -> { logD("Navigating to another album") findNavController() - .navigate(ArtistDetailFragmentDirections.actionShowAlbum(item.album.uid)) + .navigateSafe(ArtistDetailFragmentDirections.actionShowAlbum(item.album.uid)) } // Launch a new detail view for an album, even if it is part of // this artist. is Album -> { logD("Navigating to another album") findNavController() - .navigate(ArtistDetailFragmentDirections.actionShowAlbum(item.uid)) + .navigateSafe(ArtistDetailFragmentDirections.actionShowAlbum(item.uid)) } // If the artist that should be navigated to is this artist, then // scroll back to the top. Otherwise launch a new detail view. @@ -244,7 +240,7 @@ class ArtistDetailFragment : } else { logD("Navigating to another artist") findNavController() - .navigate(ArtistDetailFragmentDirections.actionShowArtist(item.uid)) + .navigateSafe(ArtistDetailFragmentDirections.actionShowArtist(item.uid)) } } null -> {} diff --git a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt index a51387a28..62ff03034 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -43,11 +43,7 @@ import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.NavigationViewModel -import org.oxycblt.auxio.util.collect -import org.oxycblt.auxio.util.collectImmediately -import org.oxycblt.auxio.util.logD -import org.oxycblt.auxio.util.showToast -import org.oxycblt.auxio.util.unlikelyToBeNull +import org.oxycblt.auxio.util.* /** * A [ListFragment] that shows information for a particular [Genre]. @@ -216,17 +212,17 @@ class GenreDetailFragment : is Song -> { logD("Navigating to another song") findNavController() - .navigate(GenreDetailFragmentDirections.actionShowAlbum(item.album.uid)) + .navigateSafe(GenreDetailFragmentDirections.actionShowAlbum(item.album.uid)) } is Album -> { logD("Navigating to another album") findNavController() - .navigate(GenreDetailFragmentDirections.actionShowAlbum(item.uid)) + .navigateSafe(GenreDetailFragmentDirections.actionShowAlbum(item.uid)) } is Artist -> { logD("Navigating to another artist") findNavController() - .navigate(GenreDetailFragmentDirections.actionShowArtist(item.uid)) + .navigateSafe(GenreDetailFragmentDirections.actionShowArtist(item.uid)) } is Genre -> { navModel.exploreNavigationItem.consume() diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt index c021febe2..65b9e6f35 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -201,7 +201,7 @@ class HomeFragment : R.id.action_search -> { logD("Navigating to search") setupAxisTransitions(MaterialSharedAxis.Z) - findNavController().navigate(HomeFragmentDirections.actionShowSearch()) + findNavController().navigateSafe(HomeFragmentDirections.actionShowSearch()) } R.id.action_settings -> { logD("Navigating to settings") @@ -454,7 +454,7 @@ class HomeFragment : } setupAxisTransitions(MaterialSharedAxis.X) - findNavController().navigate(action) + findNavController().navigateSafe(action) } private fun updateSelection(selected: List) { diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt index c724e2f39..35ff34079 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -186,7 +186,7 @@ class SearchFragment : ListFragment() { } // Keyboard is no longer needed. hideKeyboard() - findNavController().navigate(action) + findNavController().navigateSafe(action) } private fun updateSelection(selected: List) { diff --git a/app/src/main/java/org/oxycblt/auxio/settings/RootPreferenceFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/RootPreferenceFragment.kt index 39b69d817..150faea0e 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/RootPreferenceFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/RootPreferenceFragment.kt @@ -30,6 +30,7 @@ import org.oxycblt.auxio.R import org.oxycblt.auxio.music.MusicViewModel import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.settings.ui.WrappedDialogPreference +import org.oxycblt.auxio.util.navigateSafe import org.oxycblt.auxio.util.showToast /** @@ -63,19 +64,19 @@ class RootPreferenceFragment : BasePreferenceFragment(R.xml.preferences_root) { // do one. when (preference.key) { getString(R.string.set_key_ui) -> { - findNavController().navigate(RootPreferenceFragmentDirections.goToUiPreferences()) + findNavController().navigateSafe(RootPreferenceFragmentDirections.goToUiPreferences()) } getString(R.string.set_key_personalize) -> { findNavController() - .navigate(RootPreferenceFragmentDirections.goToPersonalizePreferences()) + .navigateSafe(RootPreferenceFragmentDirections.goToPersonalizePreferences()) } getString(R.string.set_key_music) -> { findNavController() - .navigate(RootPreferenceFragmentDirections.goToMusicPreferences()) + .navigateSafe(RootPreferenceFragmentDirections.goToMusicPreferences()) } getString(R.string.set_key_audio) -> { findNavController() - .navigate(RootPreferenceFragmentDirections.goToAudioPreferences()) + .navigateSafe(RootPreferenceFragmentDirections.goToAudioPreferences()) } getString(R.string.set_key_reindex) -> musicModel.refresh() getString(R.string.set_key_rescan) -> musicModel.rescan() diff --git a/app/src/main/java/org/oxycblt/auxio/settings/categories/AudioPreferenceFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/categories/AudioPreferenceFragment.kt index 54b0fbdf9..49eda0656 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/categories/AudioPreferenceFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/categories/AudioPreferenceFragment.kt @@ -22,6 +22,7 @@ import androidx.navigation.fragment.findNavController import org.oxycblt.auxio.R import org.oxycblt.auxio.settings.BasePreferenceFragment import org.oxycblt.auxio.settings.ui.WrappedDialogPreference +import org.oxycblt.auxio.util.navigateSafe /** * Audio settings interface. @@ -32,7 +33,7 @@ class AudioPreferenceFragment : BasePreferenceFragment(R.xml.preferences_audio) override fun onOpenDialogPreference(preference: WrappedDialogPreference) { if (preference.key == getString(R.string.set_key_pre_amp)) { - findNavController().navigate(AudioPreferenceFragmentDirections.goToPreAmpDialog()) + findNavController().navigateSafe(AudioPreferenceFragmentDirections.goToPreAmpDialog()) } } } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/categories/MusicPreferenceFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/categories/MusicPreferenceFragment.kt index a8a89ff2f..707747e4d 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/categories/MusicPreferenceFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/categories/MusicPreferenceFragment.kt @@ -26,6 +26,7 @@ import javax.inject.Inject import org.oxycblt.auxio.R import org.oxycblt.auxio.settings.BasePreferenceFragment import org.oxycblt.auxio.settings.ui.WrappedDialogPreference +import org.oxycblt.auxio.util.navigateSafe /** * "Content" settings. @@ -38,7 +39,7 @@ class MusicPreferenceFragment : BasePreferenceFragment(R.xml.preferences_music) override fun onOpenDialogPreference(preference: WrappedDialogPreference) { if (preference.key == getString(R.string.set_key_separators)) { - findNavController().navigate(MusicPreferenceFragmentDirections.goToSeparatorsDialog()) + findNavController().navigateSafe(MusicPreferenceFragmentDirections.goToSeparatorsDialog()) } } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/categories/PersonalizePreferenceFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/categories/PersonalizePreferenceFragment.kt index e084640da..41ac9994a 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/categories/PersonalizePreferenceFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/categories/PersonalizePreferenceFragment.kt @@ -22,6 +22,7 @@ import androidx.navigation.fragment.findNavController import org.oxycblt.auxio.R import org.oxycblt.auxio.settings.BasePreferenceFragment import org.oxycblt.auxio.settings.ui.WrappedDialogPreference +import org.oxycblt.auxio.util.navigateSafe /** * Personalization settings interface. @@ -31,7 +32,7 @@ import org.oxycblt.auxio.settings.ui.WrappedDialogPreference class PersonalizePreferenceFragment : BasePreferenceFragment(R.xml.preferences_personalize) { override fun onOpenDialogPreference(preference: WrappedDialogPreference) { if (preference.key == getString(R.string.set_key_home_tabs)) { - findNavController().navigate(PersonalizePreferenceFragmentDirections.goToTabDialog()) + findNavController().navigateSafe(PersonalizePreferenceFragmentDirections.goToTabDialog()) } } } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/categories/UIPreferenceFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/categories/UIPreferenceFragment.kt index 1a31f7369..b1105f123 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/categories/UIPreferenceFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/categories/UIPreferenceFragment.kt @@ -28,6 +28,7 @@ import org.oxycblt.auxio.settings.BasePreferenceFragment import org.oxycblt.auxio.settings.ui.WrappedDialogPreference import org.oxycblt.auxio.ui.UISettings import org.oxycblt.auxio.util.isNight +import org.oxycblt.auxio.util.navigateSafe /** * Display preferences. @@ -40,7 +41,7 @@ class UIPreferenceFragment : BasePreferenceFragment(R.xml.preferences_ui) { override fun onOpenDialogPreference(preference: WrappedDialogPreference) { if (preference.key == getString(R.string.set_key_accent)) { - findNavController().navigate(UIPreferenceFragmentDirections.goToAccentDialog()) + findNavController().navigateSafe(UIPreferenceFragmentDirections.goToAccentDialog()) } } diff --git a/app/src/main/java/org/oxycblt/auxio/util/FrameworkUtil.kt b/app/src/main/java/org/oxycblt/auxio/util/FrameworkUtil.kt index 9cabf440e..0a071092a 100644 --- a/app/src/main/java/org/oxycblt/auxio/util/FrameworkUtil.kt +++ b/app/src/main/java/org/oxycblt/auxio/util/FrameworkUtil.kt @@ -29,6 +29,9 @@ import androidx.appcompat.widget.AppCompatButton import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.graphics.Insets import androidx.core.graphics.drawable.DrawableCompat +import androidx.navigation.NavAction +import androidx.navigation.NavController +import androidx.navigation.NavDirections import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding @@ -113,6 +116,17 @@ fun AppCompatButton.fixDoubleRipple() { } } +/** + * Crash-safe wrapped around [NavController.navigate] that will not crash if multiple destinations + * are selected at once. + * @param directions The [NavDirections] to navigate with. + */ +fun NavController.navigateSafe(directions: NavDirections) = try { + navigate(directions) +} catch (e: IllegalStateException) { + // Nothing to do. +} + /** * Get the [CoordinatorLayout.Behavior] of a [View], or null if the [View] is not part of a * [CoordinatorLayout] or does not have a [CoordinatorLayout.Behavior]. @@ -149,7 +163,7 @@ val WindowInsets.systemGestureInsetsCompat: Insets // this should allow this code to fall back to system bar insets easily if the system // does not provide system gesture insets. This does require androidx Insets to allow // us to use the max method on all versions however, so we will want to convert the - // system-provided insets to such.. + // system-provided insets to such. when { Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> { // API 30+, use window inset map.