ui: return to old nested nav

It just...started working again. Beats me why.

Start using it again, but with most of the changes in-tact. I like the
way it looks.
This commit is contained in:
Alexander Capehart 2023-07-22 12:09:44 -06:00
parent 84a90e0364
commit 4b49174ced
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
12 changed files with 170 additions and 126 deletions

View file

@ -31,14 +31,18 @@ import androidx.fragment.app.activityViewModels
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavDestination import androidx.navigation.NavDestination
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import com.google.android.material.R as MR import com.google.android.material.R as MR
import com.google.android.material.bottomsheet.BackportBottomSheetBehavior import com.google.android.material.bottomsheet.BackportBottomSheetBehavior
import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.transition.MaterialFadeThrough
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import org.oxycblt.auxio.databinding.FragmentMainBinding import org.oxycblt.auxio.databinding.FragmentMainBinding
import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.home.HomeViewModel
import org.oxycblt.auxio.home.Outer
import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.list.ListViewModel
import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
@ -53,6 +57,7 @@ import org.oxycblt.auxio.util.coordinatorLayoutBehavior
import org.oxycblt.auxio.util.getAttrColorCompat import org.oxycblt.auxio.util.getAttrColorCompat
import org.oxycblt.auxio.util.getDimen import org.oxycblt.auxio.util.getDimen
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.systemBarInsetsCompat import org.oxycblt.auxio.util.systemBarInsetsCompat
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
@ -66,9 +71,10 @@ class MainFragment :
ViewBindingFragment<FragmentMainBinding>(), ViewBindingFragment<FragmentMainBinding>(),
ViewTreeObserver.OnPreDrawListener, ViewTreeObserver.OnPreDrawListener,
NavController.OnDestinationChangedListener { NavController.OnDestinationChangedListener {
private val playbackModel: PlaybackViewModel by activityViewModels()
private val listModel: ListViewModel by activityViewModels()
private val detailModel: DetailViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels()
private val homeModel: HomeViewModel by activityViewModels()
private val listModel: ListViewModel by activityViewModels()
private val playbackModel: PlaybackViewModel by activityViewModels()
private var sheetBackCallback: SheetBackPressedCallback? = null private var sheetBackCallback: SheetBackPressedCallback? = null
private var detailBackCallback: DetailBackPressedCallback? = null private var detailBackCallback: DetailBackPressedCallback? = null
private var selectionBackCallback: SelectionBackPressedCallback? = null private var selectionBackCallback: SelectionBackPressedCallback? = null
@ -77,6 +83,12 @@ class MainFragment :
private var elevationNormal = 0f private var elevationNormal = 0f
private var initialNavDestinationChange = true private var initialNavDestinationChange = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialFadeThrough()
exitTransition = MaterialFadeThrough()
}
override fun onCreateBinding(inflater: LayoutInflater) = FragmentMainBinding.inflate(inflater) override fun onCreateBinding(inflater: LayoutInflater) = FragmentMainBinding.inflate(inflater)
override fun onBindingCreated(binding: FragmentMainBinding, savedInstanceState: Bundle?) { override fun onBindingCreated(binding: FragmentMainBinding, savedInstanceState: Bundle?) {
@ -152,6 +164,7 @@ class MainFragment :
// --- VIEWMODEL SETUP --- // --- VIEWMODEL SETUP ---
collectImmediately(detailModel.editedPlaylist, detailBackCallback::invalidateEnabled) collectImmediately(detailModel.editedPlaylist, detailBackCallback::invalidateEnabled)
collectImmediately(homeModel.showOuter.flow, ::handleShowOuter)
collectImmediately(listModel.selected, selectionBackCallback::invalidateEnabled) collectImmediately(listModel.selected, selectionBackCallback::invalidateEnabled)
collectImmediately(playbackModel.song, ::updateSong) collectImmediately(playbackModel.song, ::updateSong)
collectImmediately(playbackModel.openPanel.flow, ::handlePanel) collectImmediately(playbackModel.openPanel.flow, ::handlePanel)
@ -292,6 +305,17 @@ class MainFragment :
listModel.dropSelection() listModel.dropSelection()
} }
private fun handleShowOuter(outer: Outer?) {
val directions =
when (outer) {
is Outer.Settings -> MainFragmentDirections.preferences()
is Outer.About -> MainFragmentDirections.about()
null -> return
}
findNavController().navigateSafe(directions)
homeModel.showOuter.consume()
}
private fun updateSong(song: Song?) { private fun updateSong(song: Song?) {
if (song != null) { if (song != null) {
tryShowSheets() tryShowSheets()

View file

@ -38,7 +38,6 @@ import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
import com.google.android.material.transition.MaterialFadeThrough
import com.google.android.material.transition.MaterialSharedAxis import com.google.android.material.transition.MaterialSharedAxis
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import java.lang.reflect.Field import java.lang.reflect.Field
@ -102,10 +101,9 @@ class HomeFragment :
// Orientation change will wipe whatever transition we were using prior, which will // Orientation change will wipe whatever transition we were using prior, which will
// result in no transition when the user navigates back. Make sure we re-initialize // result in no transition when the user navigates back. Make sure we re-initialize
// our transitions. // our transitions.
when (val id = savedInstanceState.getInt(KEY_LAST_TRANSITION_ID, -2)) { val axis = savedInstanceState.getInt(KEY_LAST_TRANSITION_ID, -1)
-2 -> {} if (axis > -1) {
-1 -> applyFadeTransition() applyAxisTransition(axis)
else -> applyAxisTransition(id)
} }
} }
} }
@ -183,9 +181,9 @@ class HomeFragment :
} }
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
when (val transition = enterTransition) { val transition = enterTransition
is MaterialFadeThrough -> outState.putInt(KEY_LAST_TRANSITION_ID, -1) if (transition is MaterialSharedAxis) {
is MaterialSharedAxis -> outState.putInt(KEY_LAST_TRANSITION_ID, transition.axis) outState.putInt(KEY_LAST_TRANSITION_ID, transition.axis)
} }
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
@ -224,14 +222,12 @@ class HomeFragment :
} }
R.id.action_settings -> { R.id.action_settings -> {
logD("Navigating to preferences") logD("Navigating to preferences")
applyFadeTransition() homeModel.showSettings()
findNavController().navigateSafe(HomeFragmentDirections.preferences())
true true
} }
R.id.action_about -> { R.id.action_about -> {
logD("Navigating to about") logD("Navigating to about")
applyFadeTransition() homeModel.showAbout()
findNavController().navigateSafe(HomeFragmentDirections.about())
true true
} }
@ -612,13 +608,6 @@ class HomeFragment :
reenterTransition = MaterialSharedAxis(axis, false) reenterTransition = MaterialSharedAxis(axis, false)
} }
private fun applyFadeTransition() {
enterTransition = MaterialFadeThrough()
returnTransition = MaterialFadeThrough()
exitTransition = MaterialFadeThrough()
reenterTransition = MaterialFadeThrough()
}
/** /**
* [FragmentStateAdapter] implementation for the [HomeFragment]'s [ViewPager2] instance. * [FragmentStateAdapter] implementation for the [HomeFragment]'s [ViewPager2] instance.
* *

View file

@ -131,6 +131,10 @@ constructor(
/** A marker for whether the user is fast-scrolling in the home view or not. */ /** A marker for whether the user is fast-scrolling in the home view or not. */
val isFastScrolling: StateFlow<Boolean> = _isFastScrolling val isFastScrolling: StateFlow<Boolean> = _isFastScrolling
private val _showOuter = MutableEvent<Outer>()
val showOuter: Event<Outer>
get() = _showOuter
init { init {
musicRepository.addUpdateListener(this) musicRepository.addUpdateListener(this)
homeSettings.registerListener(this) homeSettings.registerListener(this)
@ -265,6 +269,14 @@ constructor(
_isFastScrolling.value = isFastScrolling _isFastScrolling.value = isFastScrolling
} }
fun showSettings() {
_showOuter.put(Outer.Settings)
}
fun showAbout() {
_showOuter.put(Outer.About)
}
/** /**
* Create a list of [MusicType]s representing a simpler version of the [Tab] configuration. * Create a list of [MusicType]s representing a simpler version of the [Tab] configuration.
* *
@ -274,3 +286,8 @@ constructor(
private fun makeTabTypes() = private fun makeTabTypes() =
homeSettings.homeTabs.filterIsInstance<Tab.Visible>().map { it.type } homeSettings.homeTabs.filterIsInstance<Tab.Visible>().map { it.type }
} }
sealed interface Outer {
object Settings : Outer
object About : Outer
}

View file

@ -196,7 +196,6 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
} }
override fun onRoundModeChanged() { override fun onRoundModeChanged() {
// TODO: Make this a recreate as soon as you can make the bottom sheet stop freaking out
cornerRadiusRes = getCornerRadiusRes() cornerRadiusRes = getCornerRadiusRes()
applyBackgroundsToChildren() applyBackgroundsToChildren()
val cover = currentCover ?: return val cover = currentCover ?: return

View file

@ -80,7 +80,7 @@ class SongMenuDialogFragment : MenuDialogFragment<Menu.ForSong>() {
requireContext().showToast(R.string.lng_queue_added) requireContext().showToast(R.string.lng_queue_added)
} }
R.id.action_artist_details -> detailModel.showArtist(menu.song) R.id.action_artist_details -> detailModel.showArtist(menu.song)
R.id.action_album_details -> detailModel.showAlbum(menu.song) R.id.action_album_details -> detailModel.showAlbum(menu.song.album)
R.id.action_share -> requireContext().share(menu.song) R.id.action_share -> requireContext().share(menu.song)
R.id.action_playlist_add -> musicModel.addToPlaylist(menu.song) R.id.action_playlist_add -> musicModel.addToPlaylist(menu.song)
R.id.action_detail -> detailModel.showSong(menu.song) R.id.action_detail -> detailModel.showSong(menu.song)

View file

@ -2,7 +2,7 @@
<set xmlns:android="http://schemas.android.com/apk/res/android" <set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@integer/m3_sys_motion_duration_medium4" android:duration="@integer/m3_sys_motion_duration_medium4"
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized"> android:interpolator="@interpolator/m3_sys_motion_easing_emphasized">
<!-- Workaround for ugly default bottom sheet dialog transition --> <!-- Replacement for ugly default bottom sheet dialog transition -->
<translate <translate
android:fromYDelta="100%p" android:fromYDelta="100%p"
android:toYDelta="0" /> android:toYDelta="0" />

View file

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" <set xmlns:android="http://schemas.android.com/apk/res/android">
android:duration="@integer/m3_sys_motion_duration_medium3" <!-- Replacement for ugly default bottom sheet dialog transition -->
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized">
<!-- Workaround for ugly default bottom sheet dialog transition -->
<translate <translate
android:duration="@integer/m3_sys_motion_duration_medium3"
android:fromYDelta="0" android:fromYDelta="0"
android:interpolator="@interpolator/m3_sys_motion_easing_emphasized"
android:toYDelta="100%p" /> android:toYDelta="100%p" />
</set> </set>

View file

@ -13,7 +13,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_behavior="org.oxycblt.auxio.ui.BottomSheetContentBehavior" app:layout_behavior="org.oxycblt.auxio.ui.BottomSheetContentBehavior"
app:navGraph="@navigation/main" app:navGraph="@navigation/inner"
app:defaultNavHost="true" app:defaultNavHost="true"
tools:layout="@layout/fragment_home" /> tools:layout="@layout/fragment_home" />

View file

@ -3,8 +3,10 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_host" android:id="@+id/nav_host"
android:name="org.oxycblt.auxio.MainFragment" android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorSurface" android:background="?attr/colorSurface"
app:defaultNavHost="true"
app:navGraph="@navigation/outer"
tools:layout="@layout/fragment_main" /> tools:layout="@layout/fragment_main" />

View file

@ -14,7 +14,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_behavior="org.oxycblt.auxio.ui.BottomSheetContentBehavior" app:layout_behavior="org.oxycblt.auxio.ui.BottomSheetContentBehavior"
app:navGraph="@navigation/main" app:navGraph="@navigation/inner"
app:defaultNavHost="true" app:defaultNavHost="true"
tools:layout="@layout/fragment_home" /> tools:layout="@layout/fragment_home" />

View file

@ -12,12 +12,6 @@
<action <action
android:id="@+id/search" android:id="@+id/search"
app:destination="@id/search_fragment" /> app:destination="@id/search_fragment" />
<action
android:id="@+id/preferences"
app:destination="@id/root_preferences_fragment" />
<action
android:id="@+id/about"
app:destination="@id/about_fragment" />
<action <action
android:id="@+id/show_song" android:id="@+id/show_song"
app:destination="@id/song_detail_dialog" /> app:destination="@id/song_detail_dialog" />
@ -394,93 +388,4 @@
android:name="parcel" android:name="parcel"
app:argType="org.oxycblt.auxio.list.Menu$ForPlaylist$Parcel" /> app:argType="org.oxycblt.auxio.list.Menu$ForPlaylist$Parcel" />
</dialog> </dialog>
<fragment
android:id="@+id/root_preferences_fragment"
android:name="org.oxycblt.auxio.settings.RootPreferenceFragment"
android:label="fragment_settings">
<action
android:id="@+id/ui_preferences"
app:destination="@id/ui_preferences_fragment" />
<action
android:id="@+id/personalize_preferences"
app:destination="@id/personalize_preferences_fragment" />
<action
android:id="@+id/music_preferences"
app:destination="@id/music_preferences_fragment" />
<action
android:id="@+id/audio_peferences"
app:destination="@id/audio_preferences_fragment" />
<action
android:id="@+id/music_dirs_settings"
app:destination="@id/music_dirs_dialog" />
</fragment>
<fragment
android:id="@+id/ui_preferences_fragment"
android:name="org.oxycblt.auxio.settings.categories.UIPreferenceFragment"
android:label="fragment_ui_preferences">
<action
android:id="@+id/accent_settings"
app:destination="@id/accent_dialog" />
</fragment>
<fragment
android:id="@+id/personalize_preferences_fragment"
android:name="org.oxycblt.auxio.settings.categories.PersonalizePreferenceFragment"
android:label="fragment_personalize_preferences">
<action
android:id="@+id/tab_settings"
app:destination="@id/tab_dialog" />
</fragment>
<fragment
android:id="@+id/music_preferences_fragment"
android:name="org.oxycblt.auxio.settings.categories.MusicPreferenceFragment"
android:label="fragment_personalize_preferences">
<action
android:id="@+id/separators_settings"
app:destination="@id/separators_dialog" />
</fragment>
<fragment
android:id="@+id/audio_preferences_fragment"
android:name="org.oxycblt.auxio.settings.categories.AudioPreferenceFragment"
android:label="fragment_personalize_preferences">
<action
android:id="@+id/pre_amp_settings"
app:destination="@id/pre_amp_dialog" />
</fragment>
<dialog
android:id="@+id/accent_dialog"
android:name="org.oxycblt.auxio.ui.accent.AccentCustomizeDialog"
android:label="accent_dialog"
tools:layout="@layout/dialog_accent" />
<dialog
android:id="@+id/tab_dialog"
android:name="org.oxycblt.auxio.home.tabs.TabCustomizeDialog"
android:label="tab_dialog"
tools:layout="@layout/dialog_tabs" />
<dialog
android:id="@+id/pre_amp_dialog"
android:name="org.oxycblt.auxio.playback.replaygain.PreAmpCustomizeDialog"
android:label="pre_amp_dialog"
tools:layout="@layout/dialog_pre_amp" />
<dialog
android:id="@+id/music_dirs_dialog"
android:name="org.oxycblt.auxio.music.fs.MusicDirsDialog"
android:label="music_dirs_dialog"
tools:layout="@layout/dialog_music_dirs" />
<dialog
android:id="@+id/separators_dialog"
android:name="org.oxycblt.auxio.music.metadata.SeparatorsDialog"
android:label="music_dirs_dialog"
tools:layout="@layout/dialog_separators" />
<fragment
android:id="@+id/about_fragment"
android:name="org.oxycblt.auxio.settings.AboutFragment"
android:label="dialog_about"
tools:layout="@layout/fragment_about" />
</navigation> </navigation>

View file

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/absurd"
app:startDestination="@id/main_fragment">
<fragment
android:id="@+id/main_fragment"
android:name="org.oxycblt.auxio.MainFragment"
android:label="fragment_main"
tools:layout="@layout/fragment_main">
<action
android:id="@+id/preferences"
app:destination="@id/root_preferences_fragment" />
<action
android:id="@+id/about"
app:destination="@id/about_fragment" />
</fragment>
<fragment
android:id="@+id/root_preferences_fragment"
android:name="org.oxycblt.auxio.settings.RootPreferenceFragment"
android:label="fragment_settings">
<action
android:id="@+id/ui_preferences"
app:destination="@id/ui_preferences_fragment" />
<action
android:id="@+id/personalize_preferences"
app:destination="@id/personalize_preferences_fragment" />
<action
android:id="@+id/music_preferences"
app:destination="@id/music_preferences_fragment" />
<action
android:id="@+id/audio_peferences"
app:destination="@id/audio_preferences_fragment" />
<action
android:id="@+id/music_dirs_settings"
app:destination="@id/music_dirs_dialog" />
</fragment>
<fragment
android:id="@+id/ui_preferences_fragment"
android:name="org.oxycblt.auxio.settings.categories.UIPreferenceFragment"
android:label="fragment_ui_preferences">
<action
android:id="@+id/accent_settings"
app:destination="@id/accent_dialog" />
</fragment>
<fragment
android:id="@+id/personalize_preferences_fragment"
android:name="org.oxycblt.auxio.settings.categories.PersonalizePreferenceFragment"
android:label="fragment_personalize_preferences">
<action
android:id="@+id/tab_settings"
app:destination="@id/tab_dialog" />
</fragment>
<fragment
android:id="@+id/music_preferences_fragment"
android:name="org.oxycblt.auxio.settings.categories.MusicPreferenceFragment"
android:label="fragment_personalize_preferences">
<action
android:id="@+id/separators_settings"
app:destination="@id/separators_dialog" />
</fragment>
<fragment
android:id="@+id/audio_preferences_fragment"
android:name="org.oxycblt.auxio.settings.categories.AudioPreferenceFragment"
android:label="fragment_personalize_preferences">
<action
android:id="@+id/pre_amp_settings"
app:destination="@id/pre_amp_dialog" />
</fragment>
<dialog
android:id="@+id/accent_dialog"
android:name="org.oxycblt.auxio.ui.accent.AccentCustomizeDialog"
android:label="accent_dialog"
tools:layout="@layout/dialog_accent" />
<dialog
android:id="@+id/tab_dialog"
android:name="org.oxycblt.auxio.home.tabs.TabCustomizeDialog"
android:label="tab_dialog"
tools:layout="@layout/dialog_tabs" />
<dialog
android:id="@+id/pre_amp_dialog"
android:name="org.oxycblt.auxio.playback.replaygain.PreAmpCustomizeDialog"
android:label="pre_amp_dialog"
tools:layout="@layout/dialog_pre_amp" />
<dialog
android:id="@+id/music_dirs_dialog"
android:name="org.oxycblt.auxio.music.fs.MusicDirsDialog"
android:label="music_dirs_dialog"
tools:layout="@layout/dialog_music_dirs" />
<dialog
android:id="@+id/separators_dialog"
android:name="org.oxycblt.auxio.music.metadata.SeparatorsDialog"
android:label="music_dirs_dialog"
tools:layout="@layout/dialog_separators" />
<fragment
android:id="@+id/about_fragment"
android:name="org.oxycblt.auxio.settings.AboutFragment"
android:label="dialog_about"
tools:layout="@layout/fragment_about" />
</navigation>