#28: Auto update favorites list

- Also removes duplicate favorite listeners
This commit is contained in:
Ryan Harg 2021-09-10 13:36:28 +02:00
parent 687c61ed13
commit d8f8c3c193
No known key found for this signature in database
GPG Key ID: 89106F3A84E6958C
13 changed files with 109 additions and 123 deletions

View File

@ -3,9 +3,11 @@ package audio.funkwhale.ffa.activities
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import audio.funkwhale.ffa.adapters.FavoriteListener
import audio.funkwhale.ffa.adapters.SearchAdapter
import audio.funkwhale.ffa.databinding.ActivitySearchBinding
import audio.funkwhale.ffa.fragments.AddToPlaylistDialog
@ -51,7 +53,12 @@ class SearchActivity : AppCompatActivity() {
setContentView(binding.root)
adapter =
SearchAdapter(layoutInflater, this, SearchResultClickListener(), FavoriteListener()).also {
SearchAdapter(
layoutInflater,
this,
SearchResultClickListener(),
FavoriteListener(favoritesRepository)
).also {
binding.results.layoutManager = LinearLayoutManager(this)
binding.results.adapter = it
}
@ -90,59 +97,59 @@ class SearchActivity : AppCompatActivity() {
tracksRepository = TracksSearchRepository(this@SearchActivity, "")
favoritesRepository = FavoritesRepository(this@SearchActivity)
binding.search.setOnQueryTextListener(object :
androidx.appcompat.widget.SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(rawQuery: String?): Boolean {
binding.search.clearFocus()
binding.search.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
rawQuery?.let {
done = 0
override fun onQueryTextSubmit(rawQuery: String?): Boolean {
binding.search.clearFocus()
val query = URLEncoder.encode(it, "UTF-8")
rawQuery?.let {
done = 0
artistsRepository.query = query.lowercase(Locale.ROOT)
albumsRepository.query = query.lowercase(Locale.ROOT)
tracksRepository.query = query.lowercase(Locale.ROOT)
val query = URLEncoder.encode(it, "UTF-8")
binding.searchSpinner.visibility = View.VISIBLE
binding.searchEmpty.visibility = View.GONE
binding.searchNoResults.visibility = View.GONE
artistsRepository.query = query.lowercase(Locale.ROOT)
albumsRepository.query = query.lowercase(Locale.ROOT)
tracksRepository.query = query.lowercase(Locale.ROOT)
adapter.artists.clear()
adapter.albums.clear()
adapter.tracks.clear()
adapter.notifyDataSetChanged()
binding.searchSpinner.visibility = View.VISIBLE
binding.searchEmpty.visibility = View.GONE
binding.searchNoResults.visibility = View.GONE
artistsRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { artists, _, _, _ ->
done++
adapter.artists.clear()
adapter.albums.clear()
adapter.tracks.clear()
adapter.notifyDataSetChanged()
adapter.artists.addAll(artists)
refresh()
}
artistsRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { artists, _, _, _ ->
done++
albumsRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { albums, _, _, _ ->
done++
adapter.artists.addAll(artists)
refresh()
}
adapter.albums.addAll(albums)
refresh()
}
albumsRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { albums, _, _, _ ->
done++
tracksRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { tracks, _, _, _ ->
done++
adapter.albums.addAll(albums)
refresh()
}
adapter.tracks.addAll(tracks)
refresh()
}
}
tracksRepository.fetch(Repository.Origin.Network.origin)
.untilNetwork(lifecycleScope) { tracks, _, _, _ ->
done++
return true
adapter.tracks.addAll(tracks)
refresh()
}
}
override fun onQueryTextChange(newText: String?) = true
})
return true
}
override fun onQueryTextChange(newText: String?) = true
})
}
private fun refresh() {
@ -187,13 +194,4 @@ class SearchActivity : AppCompatActivity() {
AlbumsFragment.openTracks(this@SearchActivity, album)
}
}
inner class FavoriteListener : SearchAdapter.OnFavoriteListener {
override fun onToggleFavorite(id: Int, state: Boolean) {
when (state) {
true -> favoritesRepository.addFavorite(id)
false -> favoritesRepository.deleteFavorite(id)
}
}
}
}

View File

@ -0,0 +1,13 @@
package audio.funkwhale.ffa.adapters
import audio.funkwhale.ffa.repositories.FavoritesRepository
class FavoriteListener(private val repository: FavoritesRepository) {
fun onToggleFavorite(id: Int, state: Boolean) {
when (state) {
true -> repository.addFavorite(id)
false -> repository.deleteFavorite(id)
}
}
}

View File

@ -26,18 +26,14 @@ import java.util.Collections
class FavoritesAdapter(
private val layoutInflater: LayoutInflater,
private val context: Context?,
private val favoriteListener: OnFavoriteListener,
val fromQueue: Boolean = false
private val favoriteListener: FavoriteListener,
val fromQueue: Boolean = false,
) : FFAAdapter<Track, FavoritesAdapter.ViewHolder>() {
init {
this.stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY
}
interface OnFavoriteListener {
fun onToggleFavorite(id: Int, state: Boolean)
}
private lateinit var binding: RowTrackBinding
var currentTrack: Track? = null

View File

@ -30,14 +30,10 @@ import java.util.Collections
class PlaylistTracksAdapter(
private val layoutInflater: LayoutInflater,
private val context: Context?,
private val favoriteListener: OnFavoriteListener? = null,
private val playlistListener: OnPlaylistListener? = null
private val favoriteListener: FavoriteListener,
private val playlistListener: OnPlaylistListener
) : FFAAdapter<PlaylistTrack, PlaylistTracksAdapter.ViewHolder>() {
interface OnFavoriteListener {
fun onToggleFavorite(id: Int, state: Boolean)
}
private lateinit var binding: RowTrackBinding
interface OnPlaylistListener {
@ -103,7 +99,7 @@ class PlaylistTracksAdapter(
}
holder.favorite.setOnClickListener {
favoriteListener?.let {
favoriteListener.let {
favoriteListener.onToggleFavorite(track.track.id, !track.track.favorite)
track.track.favorite = !track.track.favorite
@ -124,7 +120,7 @@ class PlaylistTracksAdapter(
R.id.track_add_to_queue -> CommandBus.send(Command.AddToQueue(listOf(track.track)))
R.id.track_play_next -> CommandBus.send(Command.PlayNext(track.track))
R.id.queue_remove -> CommandBus.send(Command.RemoveFromQueue(track.track))
R.id.track_remove_from_playlist -> playlistListener?.onRemoveTrackFromPlaylist(
R.id.track_remove_from_playlist -> playlistListener.onRemoveTrackFromPlaylist(
track.track,
position
)
@ -223,7 +219,7 @@ class PlaylistTracksAdapter(
viewHolder.itemView.background = ColorDrawable(Color.TRANSPARENT)
if (from != -1 && to != -1 && from != to) {
playlistListener?.onMoveTrack(from, to)
playlistListener.onMoveTrack(from, to)
from = -1
to = -1

View File

@ -30,8 +30,8 @@ import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
class SearchAdapter(
private val layoutInflater: LayoutInflater,
private val context: Context?,
private val listener: OnSearchResultClickListener? = null,
private val favoriteListener: OnFavoriteListener? = null
private val listener: OnSearchResultClickListener,
private val favoriteListener: FavoriteListener
) : RecyclerView.Adapter<SearchAdapter.ViewHolder>() {
interface OnSearchResultClickListener {
@ -39,10 +39,6 @@ class SearchAdapter(
fun onAlbumClick(holder: View?, album: Album)
}
interface OnFavoriteListener {
fun onToggleFavorite(id: Int, state: Boolean)
}
enum class ResultType {
Header,
Artist,
@ -244,7 +240,7 @@ class SearchAdapter(
}
rowTrackViewHolder?.favorite?.setOnClickListener {
favoriteListener?.let {
favoriteListener.let {
favoriteListener.onToggleFavorite(track.id, !track.favorite)
tracks[position - artists.size - albums.size - sectionCount].favorite =
@ -341,13 +337,13 @@ class SearchAdapter(
ResultType.Artist.ordinal -> {
val position = layoutPosition - 1
listener?.onArtistClick(view, artists[position])
listener.onArtistClick(view, artists[position])
}
ResultType.Album.ordinal -> {
val position = layoutPosition - artists.size - 2
listener?.onAlbumClick(view, albums[position])
listener.onAlbumClick(view, albums[position])
}
ResultType.Track.ordinal -> {

View File

@ -31,7 +31,7 @@ import java.util.Collections
class TracksAdapter(
private val layoutInflater: LayoutInflater,
private val context: Context?,
private val favoriteListener: OnFavoriteListener? = null,
private val favoriteListener: FavoriteListener,
val fromQueue: Boolean = false
) : FFAAdapter<Track, TracksAdapter.ViewHolder>() {
@ -39,10 +39,6 @@ class TracksAdapter(
this.stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY
}
interface OnFavoriteListener {
fun onToggleFavorite(id: Int, state: Boolean)
}
private lateinit var binding: RowTrackBinding
private lateinit var touchHelper: ItemTouchHelper
@ -101,7 +97,7 @@ class TracksAdapter(
}
holder.favorite.setOnClickListener {
favoriteListener?.let {
favoriteListener.let {
favoriteListener.onToggleFavorite(track.id, !track.favorite)
data[position].favorite = !track.favorite

View File

@ -48,6 +48,8 @@ abstract class FFAFragment<D : Any, A : FFAAdapter<D, *>>() : Fragment() {
private var moreLoading = false
private var listener: Job? = null
fun <T> repository() = repository as T
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

View File

@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import audio.funkwhale.ffa.adapters.FavoriteListener
import audio.funkwhale.ffa.adapters.FavoritesAdapter
import audio.funkwhale.ffa.databinding.FragmentFavoritesBinding
import audio.funkwhale.ffa.model.Track
@ -41,8 +42,8 @@ class FavoritesFragment : FFAFragment<Track, FavoritesAdapter>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
adapter = FavoritesAdapter(layoutInflater, context, FavoriteListener())
repository = FavoritesRepository(context)
adapter = FavoritesAdapter(layoutInflater, context, FavoriteListener(repository()))
watchEventBus()
}
@ -72,6 +73,7 @@ class FavoritesFragment : FFAFragment<Track, FavoritesAdapter>() {
}
}
refreshFavoritedTracks()
refreshDownloadedTracks()
}
@ -98,6 +100,12 @@ class FavoritesFragment : FFAFragment<Track, FavoritesAdapter>() {
}
}
private fun refreshFavoritedTracks() {
lifecycleScope.launch(Main) {
update()
}
}
private suspend fun refreshDownloadedTracks() {
val downloaded = TracksRepository.getDownloadedIds(exoDownloadManager) ?: listOf()
@ -134,15 +142,4 @@ class FavoritesFragment : FFAFragment<Track, FavoritesAdapter>() {
adapter.notifyDataSetChanged()
}
}
inner class FavoriteListener : FavoritesAdapter.OnFavoriteListener {
override fun onToggleFavorite(id: Int, state: Boolean) {
(repository as? FavoritesRepository)?.let { repository ->
when (state) {
true -> repository.addFavorite(id)
false -> repository.deleteFavorite(id)
}
}
}
}
}

View File

@ -7,8 +7,10 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import audio.funkwhale.ffa.adapters.FavoriteListener
import audio.funkwhale.ffa.adapters.TracksAdapter
import audio.funkwhale.ffa.databinding.PartialQueueBinding
import audio.funkwhale.ffa.repositories.FavoritesRepository
import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.utils.Event
@ -26,6 +28,8 @@ class LandscapeQueueFragment : Fragment() {
private var _binding: PartialQueueBinding? = null
private val binding get() = _binding!!
lateinit var favoritesRepository: FavoritesRepository
private var adapter: TracksAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
@ -41,7 +45,12 @@ class LandscapeQueueFragment : Fragment() {
): View {
_binding = PartialQueueBinding.inflate(inflater)
return binding.root.apply {
adapter = TracksAdapter(layoutInflater, context, fromQueue = true).also {
adapter = TracksAdapter(
layoutInflater,
context,
fromQueue = true,
favoriteListener = FavoriteListener(favoritesRepository)
).also {
binding.queue.layoutManager = LinearLayoutManager(context)
binding.queue.adapter = it
}

View File

@ -10,6 +10,7 @@ import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.adapters.FavoriteListener
import audio.funkwhale.ffa.adapters.PlaylistTracksAdapter
import audio.funkwhale.ffa.databinding.FragmentTracksBinding
import audio.funkwhale.ffa.model.Playlist
@ -71,7 +72,7 @@ class PlaylistTracksFragment : FFAFragment<PlaylistTrack, PlaylistTracksAdapter>
albumCover = getString("albumCover") ?: ""
}
adapter = PlaylistTracksAdapter(layoutInflater, context, FavoriteListener(), PlaylistListener())
adapter = PlaylistTracksAdapter(layoutInflater, context, FavoriteListener(favoritesRepository), PlaylistListener())
repository = PlaylistTracksRepository(context, albumId)
favoritesRepository = FavoritesRepository(context)
playlistsRepository = ManagementPlaylistsRepository(context)
@ -211,15 +212,6 @@ class PlaylistTracksFragment : FFAFragment<PlaylistTrack, PlaylistTracksAdapter>
}
}
inner class FavoriteListener : PlaylistTracksAdapter.OnFavoriteListener {
override fun onToggleFavorite(id: Int, state: Boolean) {
when (state) {
true -> favoritesRepository.addFavorite(id)
false -> favoritesRepository.deleteFavorite(id)
}
}
}
inner class PlaylistListener : PlaylistTracksAdapter.OnPlaylistListener {
override fun onMoveTrack(from: Int, to: Int) {
playlistsRepository.move(albumId, from, to)

View File

@ -9,6 +9,7 @@ import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.adapters.FavoriteListener
import audio.funkwhale.ffa.adapters.TracksAdapter
import audio.funkwhale.ffa.databinding.FragmentQueueBinding
import audio.funkwhale.ffa.repositories.FavoritesRepository
@ -62,7 +63,12 @@ class QueueFragment : BottomSheetDialogFragment() {
): View {
_binding = FragmentQueueBinding.inflate(inflater)
return binding.root.apply {
adapter = TracksAdapter(layoutInflater, context, FavoriteListener(), fromQueue = true).also {
adapter = TracksAdapter(
layoutInflater,
context,
FavoriteListener(favoritesRepository),
fromQueue = true
).also {
binding.included.queue.layoutManager = LinearLayoutManager(context)
binding.included.queue.adapter = it
}
@ -135,13 +141,4 @@ class QueueFragment : BottomSheetDialogFragment() {
}
}
}
inner class FavoriteListener : TracksAdapter.OnFavoriteListener {
override fun onToggleFavorite(id: Int, state: Boolean) {
when (state) {
true -> favoritesRepository.addFavorite(id)
false -> favoritesRepository.deleteFavorite(id)
}
}
}
}

View File

@ -12,6 +12,7 @@ import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import audio.funkwhale.ffa.R
import audio.funkwhale.ffa.adapters.FavoriteListener
import audio.funkwhale.ffa.adapters.TracksAdapter
import audio.funkwhale.ffa.databinding.FragmentTracksBinding
import audio.funkwhale.ffa.model.Album
@ -83,10 +84,11 @@ class TracksFragment : FFAFragment<Track, TracksAdapter>() {
albumCover = getString("albumCover") ?: ""
}
adapter = TracksAdapter(layoutInflater, context, FavoriteListener())
repository = TracksRepository(context, albumId)
favoritesRepository = FavoritesRepository(context)
favoritedRepository = FavoritedRepository(context)
repository = TracksRepository(context, albumId)
adapter = TracksAdapter(layoutInflater, context, FavoriteListener(favoritesRepository))
watchEventBus()
}
@ -294,13 +296,4 @@ class TracksFragment : FFAFragment<Track, TracksAdapter>() {
adapter.notifyDataSetChanged()
}
}
inner class FavoriteListener : TracksAdapter.OnFavoriteListener {
override fun onToggleFavorite(id: Int, state: Boolean) {
when (state) {
true -> favoritesRepository.addFavorite(id)
false -> favoritesRepository.deleteFavorite(id)
}
}
}
}

View File

@ -0,0 +1 @@
Automatically update the favorites list view (#28)