Fix more navigation bugs
Remove the clicklistener system I added before, as it turns out fragments arent immediately recreated if you navigate back. Fun.
This commit is contained in:
parent
69c508caec
commit
b814ac613d
14 changed files with 82 additions and 42 deletions
|
@ -31,6 +31,9 @@ TODOs surrounded with !s are things I tried to do, but failed for reasons includ
|
||||||
- ? Move into ViewPager ?
|
- ? Move into ViewPager ?
|
||||||
- ! Move Adapter functionality to ListAdapter [RecyclerView scrolls to middle/bottom when data is re-sorted] !
|
- ! Move Adapter functionality to ListAdapter [RecyclerView scrolls to middle/bottom when data is re-sorted] !
|
||||||
|
|
||||||
|
/bugs/
|
||||||
|
- Fix issue where fast navigations will cause the app to not display anything
|
||||||
|
|
||||||
To be added:
|
To be added:
|
||||||
/prefs/
|
/prefs/
|
||||||
/playback/
|
/playback/
|
|
@ -11,7 +11,8 @@
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.Base">
|
android:theme="@style/Theme.Base">
|
||||||
<activity android:name=".MainActivity"
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
android:windowSoftInputMode="adjustPan">
|
android:windowSoftInputMode="adjustPan">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
|
@ -46,9 +46,13 @@ class ArtistDetailFragment : Fragment() {
|
||||||
|
|
||||||
val albumAdapter = DetailAlbumAdapter(
|
val albumAdapter = DetailAlbumAdapter(
|
||||||
ClickListener {
|
ClickListener {
|
||||||
findNavController().navigate(
|
if (!detailModel.isNavigating) {
|
||||||
ArtistDetailFragmentDirections.actionShowAlbum(it.id, false)
|
detailModel.updateNavigationStatus(true)
|
||||||
)
|
|
||||||
|
findNavController().navigate(
|
||||||
|
ArtistDetailFragmentDirections.actionShowAlbum(it.id, false)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -91,4 +95,10 @@ class ArtistDetailFragment : Fragment() {
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
detailModel.updateNavigationStatus(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@ import org.oxycblt.auxio.music.Genre
|
||||||
import org.oxycblt.auxio.recycler.SortMode
|
import org.oxycblt.auxio.recycler.SortMode
|
||||||
|
|
||||||
class DetailViewModel : ViewModel() {
|
class DetailViewModel : ViewModel() {
|
||||||
|
private var mIsNavigating = false
|
||||||
|
val isNavigating: Boolean get() = mIsNavigating
|
||||||
|
|
||||||
private val mGenreSortMode = MutableLiveData(SortMode.ALPHA_DOWN)
|
private val mGenreSortMode = MutableLiveData(SortMode.ALPHA_DOWN)
|
||||||
val genreSortMode: LiveData<SortMode> get() = mGenreSortMode
|
val genreSortMode: LiveData<SortMode> get() = mGenreSortMode
|
||||||
|
|
||||||
|
@ -79,4 +82,8 @@ class DetailViewModel : ViewModel() {
|
||||||
else -> SortMode.NUMERIC_DOWN
|
else -> SortMode.NUMERIC_DOWN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateNavigationStatus(value: Boolean) {
|
||||||
|
mIsNavigating = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,11 +44,15 @@ class GenreDetailFragment : Fragment() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val albumAdapter = DetailArtistAdapter(
|
val artistAdapter = DetailArtistAdapter(
|
||||||
ClickListener {
|
ClickListener {
|
||||||
findNavController().navigate(
|
if (!detailModel.isNavigating) {
|
||||||
GenreDetailFragmentDirections.actionShowArtist(it.id)
|
detailModel.updateNavigationStatus(true)
|
||||||
)
|
|
||||||
|
findNavController().navigate(
|
||||||
|
GenreDetailFragmentDirections.actionShowArtist(it.id)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -56,7 +60,7 @@ class GenreDetailFragment : Fragment() {
|
||||||
binding.detailModel = detailModel
|
binding.detailModel = detailModel
|
||||||
binding.genre = detailModel.currentGenre.value
|
binding.genre = detailModel.currentGenre.value
|
||||||
|
|
||||||
binding.genreArtistRecycler.adapter = albumAdapter
|
binding.genreArtistRecycler.adapter = artistAdapter
|
||||||
binding.genreArtistRecycler.applyDivider()
|
binding.genreArtistRecycler.applyDivider()
|
||||||
binding.genreArtistRecycler.setHasFixedSize(true)
|
binding.genreArtistRecycler.setHasFixedSize(true)
|
||||||
|
|
||||||
|
@ -71,7 +75,7 @@ class GenreDetailFragment : Fragment() {
|
||||||
binding.genreSortButton.setImageResource(mode.iconRes)
|
binding.genreSortButton.setImageResource(mode.iconRes)
|
||||||
|
|
||||||
// Then update the sort mode of the artist adapter.
|
// Then update the sort mode of the artist adapter.
|
||||||
albumAdapter.submitList(
|
artistAdapter.submitList(
|
||||||
mode.getSortedArtistList(detailModel.currentGenre.value!!.artists)
|
mode.getSortedArtistList(detailModel.currentGenre.value!!.artists)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -89,4 +93,10 @@ class GenreDetailFragment : Fragment() {
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
detailModel.updateNavigationStatus(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import org.oxycblt.auxio.theme.SHOW_GENRES
|
||||||
// A Great Value androidx ListAdapter that can display three types of ViewHolders.
|
// A Great Value androidx ListAdapter that can display three types of ViewHolders.
|
||||||
class LibraryAdapter(
|
class LibraryAdapter(
|
||||||
private val showMode: Int,
|
private val showMode: Int,
|
||||||
private val listener: ClickListener<BaseModel>
|
val listener: ClickListener<BaseModel>
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
var data: List<BaseModel>
|
var data: List<BaseModel>
|
||||||
|
|
|
@ -34,6 +34,8 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
||||||
private val musicModel: MusicViewModel by activityViewModels()
|
private val musicModel: MusicViewModel by activityViewModels()
|
||||||
private val libraryModel: LibraryViewModel by activityViewModels()
|
private val libraryModel: LibraryViewModel by activityViewModels()
|
||||||
|
|
||||||
|
private lateinit var libraryAdapter: LibraryAdapter
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
@ -80,7 +82,7 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
val libraryAdapter = LibraryAdapter(
|
libraryAdapter = LibraryAdapter(
|
||||||
libraryModel.showMode.value!!,
|
libraryModel.showMode.value!!,
|
||||||
ClickListener { navToItem(it) }
|
ClickListener { navToItem(it) }
|
||||||
)
|
)
|
||||||
|
@ -132,6 +134,12 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
libraryModel.updateNavigationStatus(false)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onQueryTextSubmit(query: String): Boolean = false
|
override fun onQueryTextSubmit(query: String): Boolean = false
|
||||||
|
|
||||||
override fun onQueryTextChange(query: String): Boolean {
|
override fun onQueryTextChange(query: String): Boolean {
|
||||||
|
@ -143,14 +151,18 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
||||||
private fun navToItem(baseModel: BaseModel) {
|
private fun navToItem(baseModel: BaseModel) {
|
||||||
Log.d(this::class.simpleName, "Navigating to the detail fragment for ${baseModel.name}")
|
Log.d(this::class.simpleName, "Navigating to the detail fragment for ${baseModel.name}")
|
||||||
|
|
||||||
findNavController().navigate(
|
if (!libraryModel.isNavigating) {
|
||||||
when (baseModel) {
|
libraryModel.updateNavigationStatus(true)
|
||||||
is Genre -> MainFragmentDirections.actionShowGenre(baseModel.id)
|
|
||||||
is Artist -> MainFragmentDirections.actionShowArtist(baseModel.id)
|
|
||||||
is Album -> MainFragmentDirections.actionShowAlbum(baseModel.id, true)
|
|
||||||
|
|
||||||
else -> return
|
findNavController().navigate(
|
||||||
}
|
when (baseModel) {
|
||||||
)
|
is Genre -> MainFragmentDirections.actionShowGenre(baseModel.id)
|
||||||
|
is Artist -> MainFragmentDirections.actionShowArtist(baseModel.id)
|
||||||
|
is Album -> MainFragmentDirections.actionShowAlbum(baseModel.id, true)
|
||||||
|
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,10 @@ import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.recycler.SortMode
|
import org.oxycblt.auxio.recycler.SortMode
|
||||||
import org.oxycblt.auxio.theme.SHOW_ARTISTS
|
import org.oxycblt.auxio.theme.SHOW_ARTISTS
|
||||||
|
|
||||||
class LibraryViewModel() : ViewModel() {
|
class LibraryViewModel : ViewModel() {
|
||||||
|
private var mIsNavigating = false
|
||||||
|
val isNavigating: Boolean get() = mIsNavigating
|
||||||
|
|
||||||
// TODO: Move these to prefs when they're added
|
// TODO: Move these to prefs when they're added
|
||||||
private val mShowMode = MutableLiveData(SHOW_ARTISTS)
|
private val mShowMode = MutableLiveData(SHOW_ARTISTS)
|
||||||
val showMode: LiveData<Int> get() = mShowMode
|
val showMode: LiveData<Int> get() = mShowMode
|
||||||
|
@ -36,4 +39,8 @@ class LibraryViewModel() : ViewModel() {
|
||||||
fun updateSearchQuery(query: String) {
|
fun updateSearchQuery(query: String) {
|
||||||
mSearchQuery.value = query
|
mSearchQuery.value = query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateNavigationStatus(value: Boolean) {
|
||||||
|
mIsNavigating = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,9 @@ abstract class BaseViewHolder<T : BaseModel>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bind(model: T) {
|
fun bind(model: T) {
|
||||||
baseBinding.root.setOnClickListener { listener.onClick(model) }
|
baseBinding.root.setOnClickListener {
|
||||||
|
listener.onClick(model)
|
||||||
|
}
|
||||||
|
|
||||||
onBind(model)
|
onBind(model)
|
||||||
|
|
||||||
|
|
|
@ -5,17 +5,7 @@ import org.oxycblt.auxio.music.BaseModel
|
||||||
|
|
||||||
// A RecyclerView click listener that can only be called once.
|
// A RecyclerView click listener that can only be called once.
|
||||||
// Primarily used for navigation to prevent bugs when multiple items are selected.
|
// Primarily used for navigation to prevent bugs when multiple items are selected.
|
||||||
class ClickListener<T>(private val clickAction: (T) -> Unit) {
|
class ClickListener<T>(val onClick: (T) -> Unit)
|
||||||
private var hasClicked = false
|
|
||||||
|
|
||||||
fun onClick(item: T) {
|
|
||||||
if (!hasClicked) {
|
|
||||||
hasClicked = true
|
|
||||||
|
|
||||||
clickAction(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base Diff callback
|
// Base Diff callback
|
||||||
class DiffCallback<T : BaseModel> : DiffUtil.ItemCallback<T>() {
|
class DiffCallback<T : BaseModel> : DiffUtil.ItemCallback<T>() {
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
<!--
|
|
||||||
Custom cursor shape that reflects the current accent color.
|
Custom cursor shape that reflects the current accent color.
|
||||||
https://stackoverflow.com/a/28311351/14143986
|
https://stackoverflow.com/a/28311351/14143986
|
||||||
-->
|
-->
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle" >
|
android:shape="rectangle">
|
||||||
<solid android:color="?android:attr/colorPrimary" />
|
<solid android:color="?android:attr/colorPrimary" />
|
||||||
<size android:width="2dp" />
|
<size android:width="2dp" />
|
||||||
</shape>
|
</shape>
|
|
@ -5,7 +5,7 @@
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24"
|
android:viewportHeight="24"
|
||||||
android:tint="?attr/colorControlNormal">
|
android:tint="?attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
|
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z" />
|
||||||
</vector>
|
</vector>
|
|
@ -19,7 +19,7 @@
|
||||||
app:popupTheme="@style/AppThemeOverlay.Popup"
|
app:popupTheme="@style/AppThemeOverlay.Popup"
|
||||||
app:menu="@menu/menu_library"
|
app:menu="@menu/menu_library"
|
||||||
app:titleTextAppearance="@style/TextAppearance.Toolbar.Header"
|
app:titleTextAppearance="@style/TextAppearance.Toolbar.Header"
|
||||||
app:title="@string/title_library_fragment"/>
|
app:title="@string/title_library_fragment" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/library_recycler"
|
android:id="@+id/library_recycler"
|
||||||
|
|
|
@ -31,8 +31,7 @@
|
||||||
app:exitAnim="@anim/fragment_fade_exit"
|
app:exitAnim="@anim/fragment_fade_exit"
|
||||||
app:popEnterAnim="@anim/fragment_fade_enter"
|
app:popEnterAnim="@anim/fragment_fade_enter"
|
||||||
app:popExitAnim="@anim/fragment_fade_exit"
|
app:popExitAnim="@anim/fragment_fade_exit"
|
||||||
app:destination="@id/artist_detail_fragment"
|
app:destination="@id/artist_detail_fragment" />
|
||||||
app:launchSingleTop="true" />
|
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_show_album"
|
android:id="@+id/action_show_album"
|
||||||
app:enterAnim="@anim/fragment_fade_enter"
|
app:enterAnim="@anim/fragment_fade_enter"
|
||||||
|
|
Loading…
Reference in a new issue