1
0
mirror of https://github.com/ultrasonic/ultrasonic synced 2025-02-22 06:27:51 +01:00

Remove special casing of SongsForGenre and thereby fix it.

Also prevent jumping in the random albums list and
don't refresh the album list on back navigation
This commit is contained in:
tzugen 2021-12-05 21:07:08 +01:00
parent 6daa17efd5
commit 026aa79572
No known key found for this signature in database
GPG Key ID: 61E9C34BC10EC930
6 changed files with 60 additions and 50 deletions

View File

@ -34,6 +34,11 @@ class AlbumListFragment : EntryListFragment<MusicDirectory.Album>() {
*/ */
override val mainLayout: Int = R.layout.list_layout_generic override val mainLayout: Int = R.layout.list_layout_generic
/**
* Whether to refresh the data onViewCreated
*/
override val refreshOnCreation: Boolean = false
/** /**
* The central function to pass a query to the model and return a LiveData object * The central function to pass a query to the model and return a LiveData object
*/ */

View File

@ -71,7 +71,7 @@ abstract class EntryListFragment<T : GenericEntry> : MultiListFragment<T>() {
* What to do when the list has changed * What to do when the list has changed
*/ */
override val defaultObserver: (List<T>) -> Unit = { override val defaultObserver: (List<T>) -> Unit = {
emptyView.isVisible = it.isEmpty() emptyView.isVisible = it.isEmpty() && !(refreshListView?.isRefreshing?:false)
if (showFolderHeader()) { if (showFolderHeader()) {
val list = mutableListOf<Identifiable>(folderHeader) val list = mutableListOf<Identifiable>(folderHeader)

View File

@ -89,6 +89,11 @@ abstract class MultiListFragment<T : Identifiable> : Fragment() {
open val emptyViewId = R.id.empty_list_view open val emptyViewId = R.id.empty_list_view
open val emptyTextId = R.id.empty_list_text open val emptyTextId = R.id.empty_list_text
/**
* Whether to refresh the data onViewCreated
*/
open val refreshOnCreation: Boolean = true
open fun setTitle(title: String?) { open fun setTitle(title: String?) {
if (title == null) { if (title == null) {
FragmentTitle.setTitle( FragmentTitle.setTitle(
@ -106,7 +111,7 @@ abstract class MultiListFragment<T : Identifiable> : Fragment() {
* What to do when the list has changed * What to do when the list has changed
*/ */
internal open val defaultObserver: ((List<T>) -> Unit) = { internal open val defaultObserver: ((List<T>) -> Unit) = {
emptyView.isVisible = it.isEmpty() emptyView.isVisible = it.isEmpty() && !(refreshListView?.isRefreshing?:false)
viewAdapter.submitList(it) viewAdapter.submitList(it)
} }
@ -123,7 +128,7 @@ abstract class MultiListFragment<T : Identifiable> : Fragment() {
} }
// Populate the LiveData. This starts an API request in most cases // Populate the LiveData. This starts an API request in most cases
liveDataItems = getLiveData(arguments, true) liveDataItems = getLiveData(arguments, refreshOnCreation)
// Link view to display text if the list is empty // Link view to display text if the list is empty
emptyView = view.findViewById(emptyViewId) emptyView = view.findViewById(emptyViewId)

View File

@ -18,7 +18,6 @@ import android.widget.ImageView
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -54,6 +53,8 @@ import org.moire.ultrasonic.util.Util
* In most cases the data should be just a list of Entries, but there are some cases * In most cases the data should be just a list of Entries, but there are some cases
* where the list can contain Albums as well. This happens especially when having ID3 tags disabled, * where the list can contain Albums as well. This happens especially when having ID3 tags disabled,
* or using Offline mode, both in which Indexes instead of Artists are being used. * or using Offline mode, both in which Indexes instead of Artists are being used.
*
* TODO: Remove more button and introduce endless scrolling
*/ */
@Suppress("TooManyFunctions") @Suppress("TooManyFunctions")
open class TrackCollectionFragment : MultiListFragment<MusicDirectory.Child>() { open class TrackCollectionFragment : MultiListFragment<MusicDirectory.Child>() {
@ -97,9 +98,6 @@ open class TrackCollectionFragment : MultiListFragment<MusicDirectory.Child>() {
getLiveData(arguments, true) getLiveData(arguments, true)
} }
// TODO: remove special casing for songsForGenre
listModel.songsForGenre.observe(viewLifecycleOwner, songsForGenreObserver)
setupButtons(view) setupButtons(view)
registerForContextMenu(listView!!) registerForContextMenu(listView!!)
@ -424,34 +422,6 @@ open class TrackCollectionFragment : MultiListFragment<MusicDirectory.Child>() {
mediaPlayerController.unpin(songs) mediaPlayerController.unpin(songs)
} }
private val songsForGenreObserver = Observer<MusicDirectory> { musicDirectory ->
// Hide more button when results are less than album list size
if (musicDirectory.size < requireArguments().getInt(
Constants.INTENT_ALBUM_LIST_SIZE, 0
)
) {
moreButton!!.visibility = View.GONE
} else {
moreButton!!.visibility = View.VISIBLE
}
moreButton!!.setOnClickListener {
val theGenre = requireArguments().getString(Constants.INTENT_GENRE_NAME)
val size = requireArguments().getInt(Constants.INTENT_ALBUM_LIST_SIZE, 0)
val theOffset = requireArguments().getInt(
Constants.INTENT_ALBUM_LIST_OFFSET, 0
) + size
val bundle = Bundle()
bundle.putString(Constants.INTENT_GENRE_NAME, theGenre)
bundle.putInt(Constants.INTENT_ALBUM_LIST_SIZE, size)
bundle.putInt(Constants.INTENT_ALBUM_LIST_OFFSET, theOffset)
Navigation.findNavController(requireView())
.navigate(R.id.trackCollectionFragment, bundle)
}
}
override val defaultObserver: (List<MusicDirectory.Child>) -> Unit = { override val defaultObserver: (List<MusicDirectory.Child>) -> Unit = {
val entryList: MutableList<MusicDirectory.Child> = it.toMutableList() val entryList: MutableList<MusicDirectory.Child> = it.toMutableList()
@ -483,18 +453,9 @@ open class TrackCollectionFragment : MultiListFragment<MusicDirectory.Child>() {
} else { } else {
moreButton!!.visibility = View.VISIBLE moreButton!!.visibility = View.VISIBLE
if (arguments?.getInt(Constants.INTENT_RANDOM, 0) ?: 0 > 0) { if (arguments?.getInt(Constants.INTENT_RANDOM, 0) ?: 0 > 0) {
moreButton!!.setOnClickListener { moreRandomTracks()
val offset = requireArguments().getInt( } else if (arguments?.getString(Constants.INTENT_GENRE_NAME, "") ?: "" != "") {
Constants.INTENT_ALBUM_LIST_OFFSET, 0 moreSongsForGenre()
) + listSize
val bundle = Bundle()
bundle.putInt(Constants.INTENT_RANDOM, 1)
bundle.putInt(Constants.INTENT_ALBUM_LIST_SIZE, listSize)
bundle.putInt(Constants.INTENT_ALBUM_LIST_OFFSET, offset)
Navigation.findNavController(requireView()).navigate(
R.id.trackCollectionFragment, bundle
)
}
} }
} }
} }
@ -536,6 +497,40 @@ open class TrackCollectionFragment : MultiListFragment<MusicDirectory.Child>() {
listModel.currentListIsSortable = true listModel.currentListIsSortable = true
} }
private fun moreSongsForGenre(args: Bundle = requireArguments()) {
moreButton!!.setOnClickListener {
val theGenre = args.getString(Constants.INTENT_GENRE_NAME)
val size = args.getInt(Constants.INTENT_ALBUM_LIST_SIZE, 0)
val theOffset = args.getInt(
Constants.INTENT_ALBUM_LIST_OFFSET, 0
) + size
val bundle = Bundle()
bundle.putString(Constants.INTENT_GENRE_NAME, theGenre)
bundle.putInt(Constants.INTENT_ALBUM_LIST_SIZE, size)
bundle.putInt(Constants.INTENT_ALBUM_LIST_OFFSET, theOffset)
Navigation.findNavController(requireView())
.navigate(R.id.trackCollectionFragment, bundle)
}
}
private fun moreRandomTracks() {
val listSize = arguments?.getInt(Constants.INTENT_ALBUM_LIST_SIZE, 0) ?: 0
moreButton!!.setOnClickListener { it: View? ->
val offset = requireArguments().getInt(
Constants.INTENT_ALBUM_LIST_OFFSET, 0
) + listSize
val bundle = Bundle()
bundle.putInt(Constants.INTENT_RANDOM, 1)
bundle.putInt(Constants.INTENT_ALBUM_LIST_SIZE, listSize)
bundle.putInt(Constants.INTENT_ALBUM_LIST_OFFSET, offset)
Navigation.findNavController(requireView()).navigate(
R.id.trackCollectionFragment, bundle
)
}
}
internal fun getSelectedSongs(): List<MusicDirectory.Entry> { internal fun getSelectedSongs(): List<MusicDirectory.Entry> {
// Walk through selected set and get the Entries based on the saved ids. // Walk through selected set and get the Entries based on the saved ids.
return viewAdapter.getCurrentList().mapNotNull { return viewAdapter.getCurrentList().mapNotNull {

View File

@ -63,6 +63,12 @@ class AlbumListModel(application: Application) : GenericListModel(application) {
null null
} }
// If we are refreshing the random list, we want to avoid items moving across the screen,
// by clearing the list first
if (refresh && albumListType == "random") {
list.postValue(listOf())
}
// Handle the logic for endless scrolling: // Handle the logic for endless scrolling:
// If appending the existing list, set the offset from where to load // If appending the existing list, set the offset from where to load
if (append) offset += (size + loadedUntil) if (append) offset += (size + loadedUntil)
@ -95,7 +101,7 @@ class AlbumListModel(application: Application) : GenericListModel(application) {
val newList = ArrayList<MusicDirectory.Album>() val newList = ArrayList<MusicDirectory.Album>()
newList.addAll(list.value!!) newList.addAll(list.value!!)
newList.addAll(musicDirectory) newList.addAll(musicDirectory)
this.list.postValue(newList) list.postValue(newList)
} else { } else {
list.postValue(musicDirectory) list.postValue(musicDirectory)
} }

View File

@ -22,7 +22,6 @@ import org.moire.ultrasonic.util.Util
class TrackCollectionModel(application: Application) : GenericListModel(application) { class TrackCollectionModel(application: Application) : GenericListModel(application) {
val currentList: MutableLiveData<List<MusicDirectory.Child>> = MutableLiveData() val currentList: MutableLiveData<List<MusicDirectory.Child>> = MutableLiveData()
val songsForGenre: MutableLiveData<MusicDirectory> = MutableLiveData()
/* /*
* Especially when dealing with indexes, this method can return Albums, Entries or a mix of both! * Especially when dealing with indexes, this method can return Albums, Entries or a mix of both!
@ -56,7 +55,7 @@ class TrackCollectionModel(application: Application) : GenericListModel(applicat
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val service = MusicServiceFactory.getMusicService() val service = MusicServiceFactory.getMusicService()
val musicDirectory = service.getSongsByGenre(genre, count, offset) val musicDirectory = service.getSongsByGenre(genre, count, offset)
songsForGenre.postValue(musicDirectory) updateList(musicDirectory)
} }
} }