Fixed favorite toggle in DriveModeActivity

This commit is contained in:
Prathamesh More 2021-12-12 17:09:05 +05:30
parent 144fcf29bd
commit 421dc817a2
10 changed files with 125 additions and 95 deletions

View file

@ -15,16 +15,22 @@
package code.name.monkey.retromusic.activities package code.name.monkey.retromusic.activities
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.graphics.PorterDuff import android.graphics.PorterDuff
import android.os.Bundle import android.os.Bundle
import android.view.animation.LinearInterpolator import android.view.animation.LinearInterpolator
import android.widget.SeekBar import android.widget.SeekBar
import androidx.activity.viewModels
import androidx.lifecycle.lifecycleScope
import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
import code.name.monkey.retromusic.databinding.ActivityDriveModeBinding import code.name.monkey.retromusic.databinding.ActivityDriveModeBinding
import code.name.monkey.retromusic.extensions.setDrawUnderStatusBar import code.name.monkey.retromusic.db.toSongEntity
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.ReloadType
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.glide.BlurTransformation import code.name.monkey.retromusic.glide.BlurTransformation
import code.name.monkey.retromusic.glide.GlideApp import code.name.monkey.retromusic.glide.GlideApp
@ -35,13 +41,16 @@ import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel
/** /**
@ -54,9 +63,9 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
private var lastPlaybackControlsColor: Int = Color.GRAY private var lastPlaybackControlsColor: Int = Color.GRAY
private var lastDisabledPlaybackControlsColor: Int = Color.GRAY private var lastDisabledPlaybackControlsColor: Int = Color.GRAY
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
private val repository: RealRepository by inject()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityDriveModeBinding.inflate(layoutInflater) binding = ActivityDriveModeBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
@ -67,6 +76,7 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
binding.close.setOnClickListener { binding.close.setOnClickListener {
onBackPressed() onBackPressed()
} }
binding.repeatButton.drawAboveSystemBars()
} }
private fun setUpMusicControllers() { private fun setUpMusicControllers() {
@ -80,19 +90,32 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
private fun setupFavouriteToggle() { private fun setupFavouriteToggle() {
binding.songFavourite.setOnClickListener { binding.songFavourite.setOnClickListener {
MusicUtil.toggleFavorite( toggleFavorite(MusicPlayerRemote.currentSong)
this@DriveModeActivity,
MusicPlayerRemote.currentSong
)
} }
} }
private fun toggleFavourite() { private fun toggleFavorite(song: Song) {
CoroutineScope(Dispatchers.IO).launch { lifecycleScope.launch(Dispatchers.IO) {
val isFavourite = val playlist = repository.favoritePlaylist()
MusicUtil.isFavorite(this@DriveModeActivity, MusicPlayerRemote.currentSong) if (playlist != null) {
val songEntity = song.toSongEntity(playlist.playListId)
val isFavorite = repository.isSongFavorite(song.id)
if (isFavorite) {
repository.removeSongFromPlaylist(songEntity)
} else {
repository.insertSongs(listOf(song.toSongEntity(playlist.playListId)))
}
}
sendBroadcast(Intent(MusicService.FAVORITE_STATE_CHANGED))
}
}
private fun updateFavorite() {
lifecycleScope.launch(Dispatchers.IO) {
val isFavorite: Boolean =
repository.isSongFavorite(MusicPlayerRemote.currentSong.id)
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
binding.songFavourite.setImageResource(if (isFavourite) R.drawable.ic_favorite else R.drawable.ic_favorite_border) binding.songFavourite.setImageResource(if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border)
} }
} }
} }
@ -160,7 +183,7 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
updateSong() updateSong()
updateRepeatState() updateRepeatState()
updateShuffleState() updateShuffleState()
toggleFavourite() updateFavorite()
} }
private fun updatePlayPauseDrawableState() { private fun updatePlayPauseDrawableState() {
@ -213,7 +236,12 @@ class DriveModeActivity : AbsMusicServiceActivity(), Callback {
override fun onPlayingMetaChanged() { override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged() super.onPlayingMetaChanged()
updateSong() updateSong()
toggleFavourite() updateFavorite()
}
override fun onFavoriteStateChanged() {
super.onFavoriteStateChanged()
updateFavorite()
} }
private fun updateSong() { private fun updateSong() {

View file

@ -26,7 +26,7 @@ interface PlaylistDao {
suspend fun renamePlaylist(playlistId: Long, name: String) suspend fun renamePlaylist(playlistId: Long, name: String)
@Query("SELECT * FROM PlaylistEntity WHERE playlist_name = :name") @Query("SELECT * FROM PlaylistEntity WHERE playlist_name = :name")
fun isPlaylistExists(name: String): List<PlaylistEntity> fun playlist(name: String): List<PlaylistEntity>
@Query("SELECT * FROM PlaylistEntity") @Query("SELECT * FROM PlaylistEntity")
suspend fun playlists(): List<PlaylistEntity> suspend fun playlists(): List<PlaylistEntity>

View file

@ -233,6 +233,7 @@ class LibraryViewModel(
suspend fun artistById(id: Long) = repository.artistById(id) suspend fun artistById(id: Long) = repository.artistById(id)
suspend fun favoritePlaylist() = repository.favoritePlaylist() suspend fun favoritePlaylist() = repository.favoritePlaylist()
suspend fun isFavoriteSong(song: SongEntity) = repository.isFavoriteSong(song) suspend fun isFavoriteSong(song: SongEntity) = repository.isFavoriteSong(song)
suspend fun isSongFavorite(songId: Long) = repository.isSongFavorite(songId)
suspend fun insertSongs(songs: List<SongEntity>) = repository.insertSongs(songs) suspend fun insertSongs(songs: List<SongEntity>) = repository.insertSongs(songs)
suspend fun removeSongFromPlaylist(songEntity: SongEntity) = suspend fun removeSongFromPlaylist(songEntity: SongEntity) =
repository.removeSongFromPlaylist(songEntity) repository.removeSongFromPlaylist(songEntity)

View file

@ -38,7 +38,6 @@ import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.navOptions import androidx.navigation.navOptions
import androidx.transition.Fade
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
import code.name.monkey.retromusic.EXTRA_ALBUM_ID import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.EXTRA_ARTIST_ID import code.name.monkey.retromusic.EXTRA_ARTIST_ID
@ -232,7 +231,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
val playlist: PlaylistEntity = libraryViewModel.favoritePlaylist() val playlist: PlaylistEntity = libraryViewModel.favoritePlaylist()
if (playlist != null) { if (playlist != null) {
val songEntity = song.toSongEntity(playlist.playListId) val songEntity = song.toSongEntity(playlist.playListId)
val isFavorite = libraryViewModel.isFavoriteSong(songEntity).isNotEmpty() val isFavorite = libraryViewModel.isSongFavorite(song.id)
if (isFavorite) { if (isFavorite) {
libraryViewModel.removeSongFromPlaylist(songEntity) libraryViewModel.removeSongFromPlaylist(songEntity)
} else { } else {
@ -246,32 +245,28 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
fun updateIsFavorite(animate: Boolean = false) { fun updateIsFavorite(animate: Boolean = false) {
lifecycleScope.launch(IO) { lifecycleScope.launch(IO) {
val playlist: PlaylistEntity = libraryViewModel.favoritePlaylist() val isFavorite: Boolean =
if (playlist != null) { libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
val song: SongEntity = withContext(Main) {
MusicPlayerRemote.currentSong.toSongEntity(playlist.playListId) val icon = if (animate) {
val isFavorite: Boolean = libraryViewModel.isFavoriteSong(song).isNotEmpty() if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
withContext(Main) { } else {
val icon = if (animate) { if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite }
} else { val drawable: Drawable = RetroUtil.getTintedVectorDrawable(
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border requireContext(),
} icon,
val drawable: Drawable = RetroUtil.getTintedVectorDrawable( toolbarIconColor()
requireContext(), )
icon, if (playerToolbar() != null) {
toolbarIconColor() playerToolbar()?.menu?.findItem(R.id.action_toggle_favorite)?.apply {
) setIcon(drawable)
if (playerToolbar() != null) { title =
playerToolbar()?.menu?.findItem(R.id.action_toggle_favorite)?.apply { if (isFavorite) getString(R.string.action_remove_from_favorites)
setIcon(drawable) else getString(R.string.action_add_to_favorites)
title = getIcon().also {
if (isFavorite) getString(R.string.action_remove_from_favorites) if (it is AnimatedVectorDrawable) {
else getString(R.string.action_add_to_favorites) it.start()
getIcon().also {
if (it is AnimatedVectorDrawable) {
it.start()
}
} }
} }
} }

View file

@ -317,28 +317,24 @@ class FullPlaybackControlsFragment :
fun updateIsFavorite(animate: Boolean = false) { fun updateIsFavorite(animate: Boolean = false) {
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
val playlist: PlaylistEntity = libraryViewModel.favoritePlaylist() val isFavorite: Boolean =
if (playlist != null) { libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
val song: SongEntity = withContext(Dispatchers.Main) {
MusicPlayerRemote.currentSong.toSongEntity(playlist.playListId) val icon = if (animate) {
val isFavorite: Boolean = libraryViewModel.isFavoriteSong(song).isNotEmpty() if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
withContext(Dispatchers.Main) { } else {
val icon = if (animate) { if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite }
} else { val drawable: Drawable = RetroUtil.getTintedVectorDrawable(
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border requireContext(),
} icon,
val drawable: Drawable = RetroUtil.getTintedVectorDrawable( Color.WHITE
requireContext(), )
icon, binding.songFavourite.apply {
Color.WHITE setImageDrawable(drawable)
) getDrawable().also {
binding.songFavourite.apply { if (it is AnimatedVectorDrawable) {
setImageDrawable(drawable) it.start()
getDrawable().also {
if (it is AnimatedVectorDrawable) {
it.start()
}
} }
} }
} }

View file

@ -281,23 +281,19 @@ class GradientPlayerFragment : AbsPlayerFragment(R.layout.fragment_gradient_play
private fun updateIsFavoriteIcon(animate: Boolean = false) { private fun updateIsFavoriteIcon(animate: Boolean = false) {
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
val playlist: PlaylistEntity = libraryViewModel.favoritePlaylist() val isFavorite: Boolean =
if (playlist != null) { libraryViewModel.isSongFavorite(MusicPlayerRemote.currentSong.id)
val song: SongEntity = withContext(Dispatchers.Main) {
MusicPlayerRemote.currentSong.toSongEntity(playlist.playListId) val icon = if (animate) {
val isFavorite: Boolean = libraryViewModel.isFavoriteSong(song).isNotEmpty() if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite
withContext(Dispatchers.Main) { } else {
val icon = if (animate) { if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
if (isFavorite) R.drawable.avd_favorite else R.drawable.avd_unfavorite }
} else { binding.playbackControlsFragment.songFavourite.apply {
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border setImageResource(icon)
} drawable.also {
binding.playbackControlsFragment.songFavourite.apply { if (it is AnimatedVectorDrawable) {
setImageResource(icon) it.start()
drawable.also {
if (it is AnimatedVectorDrawable) {
it.start()
}
} }
} }
} }

View file

@ -42,7 +42,7 @@ class PlaylistsFragment :
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
libraryViewModel.getPlaylists().observe(viewLifecycleOwner, { libraryViewModel.getPlaylists().observe(viewLifecycleOwner, {
if (it.isNotEmpty()) if (it.isNotEmpty())
adapter?.swapDataSet(it.filter { playlistWithSongs-> playlistWithSongs.songs.isNotEmpty() }) adapter?.swapDataSet(it)
else else
adapter?.swapDataSet(listOf()) adapter?.swapDataSet(listOf())
}) })

View file

@ -72,6 +72,7 @@ interface Repository {
suspend fun genresHome(): Home suspend fun genresHome(): Home
suspend fun playlists(): Home suspend fun playlists(): Home
suspend fun homeSections(): List<Home> suspend fun homeSections(): List<Home>
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
suspend fun homeSectionsFlow(): Flow<Result<List<Home>>> suspend fun homeSectionsFlow(): Flow<Result<List<Home>>>
suspend fun playlist(playlistId: Long): Playlist suspend fun playlist(playlistId: Long): Playlist
@ -106,6 +107,7 @@ interface Repository {
suspend fun searchArtists(query: String): List<Artist> suspend fun searchArtists(query: String): List<Artist>
suspend fun searchSongs(query: String): List<Song> suspend fun searchSongs(query: String): List<Song>
suspend fun searchAlbums(query: String): List<Album> suspend fun searchAlbums(query: String): List<Album>
suspend fun isSongFavorite(songId: Long): Boolean
fun getSongByGenre(genreId: Long): Song fun getSongByGenre(genreId: Long): Song
} }
@ -133,6 +135,9 @@ class RealRepository(
override suspend fun searchAlbums(query: String): List<Album> = albumRepository.albums(query) override suspend fun searchAlbums(query: String): List<Album> = albumRepository.albums(query)
override suspend fun isSongFavorite(songId: Long): Boolean =
roomRepository.isSongFavorite(context, songId)
override fun getSongByGenre(genreId: Long): Song = genreRepository.song(genreId) override fun getSongByGenre(genreId: Long): Song = genreRepository.song(genreId)
override suspend fun searchArtists(query: String): List<Artist> = override suspend fun searchArtists(query: String): List<Artist> =
@ -150,7 +155,8 @@ class RealRepository(
override suspend fun artistById(artistId: Long): Artist = artistRepository.artist(artistId) override suspend fun artistById(artistId: Long): Artist = artistRepository.artist(artistId)
override suspend fun albumArtistByName(name: String): Artist = artistRepository.albumArtist(name) override suspend fun albumArtistByName(name: String): Artist =
artistRepository.albumArtist(name)
override suspend fun recentArtists(): List<Artist> = lastAddedRepository.recentArtists() override suspend fun recentArtists(): List<Artist> = lastAddedRepository.recentArtists()

View file

@ -1,7 +1,9 @@
package code.name.monkey.retromusic.repository package code.name.monkey.retromusic.repository
import android.content.Context
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.db.* import code.name.monkey.retromusic.db.*
import code.name.monkey.retromusic.helper.SortOrder.PlaylistSortOrder.Companion.PLAYLIST_A_Z import code.name.monkey.retromusic.helper.SortOrder.PlaylistSortOrder.Companion.PLAYLIST_A_Z
import code.name.monkey.retromusic.helper.SortOrder.PlaylistSortOrder.Companion.PLAYLIST_SONG_COUNT import code.name.monkey.retromusic.helper.SortOrder.PlaylistSortOrder.Companion.PLAYLIST_SONG_COUNT
@ -45,6 +47,7 @@ interface RoomRepository {
suspend fun insertBlacklistPathAsync(blackListStoreEntity: BlackListStoreEntity) suspend fun insertBlacklistPathAsync(blackListStoreEntity: BlackListStoreEntity)
suspend fun blackListPaths(): List<BlackListStoreEntity> suspend fun blackListPaths(): List<BlackListStoreEntity>
suspend fun deleteSongs(songs: List<Song>) suspend fun deleteSongs(songs: List<Song>)
suspend fun isSongFavorite(context: Context, songId: Long): Boolean
} }
class RealRoomRepository( class RealRoomRepository(
@ -60,7 +63,7 @@ class RealRoomRepository(
@WorkerThread @WorkerThread
override suspend fun checkPlaylistExists(playlistName: String): List<PlaylistEntity> = override suspend fun checkPlaylistExists(playlistName: String): List<PlaylistEntity> =
playlistDao.isPlaylistExists(playlistName) playlistDao.playlist(playlistName)
@WorkerThread @WorkerThread
override suspend fun playlists(): List<PlaylistEntity> = playlistDao.playlists() override suspend fun playlists(): List<PlaylistEntity> = playlistDao.playlists()
@ -111,12 +114,13 @@ class RealRoomRepository(
} }
override suspend fun favoritePlaylist(favorite: String): PlaylistEntity { override suspend fun favoritePlaylist(favorite: String): PlaylistEntity {
val playlist: PlaylistEntity? = playlistDao.isPlaylistExists(favorite).firstOrNull() val playlist: PlaylistEntity? = playlistDao.playlist(favorite).firstOrNull()
return if (playlist != null) { return if (playlist != null) {
playlist playlist
} else { } else {
println("Playlist Created")
createPlaylist(PlaylistEntity(playlistName = favorite)) createPlaylist(PlaylistEntity(playlistName = favorite))
playlistDao.isPlaylistExists(favorite).first() playlistDao.playlist(favorite).first()
} }
} }
@ -145,12 +149,12 @@ class RealRoomRepository(
override fun favoritePlaylistLiveData(favorite: String): LiveData<List<SongEntity>> = override fun favoritePlaylistLiveData(favorite: String): LiveData<List<SongEntity>> =
playlistDao.favoritesSongsLiveData( playlistDao.favoritesSongsLiveData(
playlistDao.isPlaylistExists(favorite).first().playListId playlistDao.playlist(favorite).first().playListId
) )
override suspend fun favoritePlaylistSongs(favorite: String): List<SongEntity> = override suspend fun favoritePlaylistSongs(favorite: String): List<SongEntity> =
if (playlistDao.isPlaylistExists(favorite).isNotEmpty()) playlistDao.favoritesSongs( if (playlistDao.playlist(favorite).isNotEmpty()) playlistDao.favoritesSongs(
playlistDao.isPlaylistExists(favorite).first().playListId playlistDao.playlist(favorite).first().playListId
) else emptyList() ) else emptyList()
override suspend fun insertSongInPlayCount(playCountEntity: PlayCountEntity) = override suspend fun insertSongInPlayCount(playCountEntity: PlayCountEntity) =
@ -192,4 +196,12 @@ class RealRoomRepository(
blackListStoreDao.deleteBlacklistPath(blackListStoreEntity) blackListStoreDao.deleteBlacklistPath(blackListStoreEntity)
override suspend fun clearBlacklist() = blackListStoreDao.clearBlacklist() override suspend fun clearBlacklist() = blackListStoreDao.clearBlacklist()
override suspend fun isSongFavorite(context: Context, songId: Long): Boolean {
return playlistDao.isSongExistsInPlaylist(
playlistDao.playlist(context.getString(R.string.favorites)).firstOrNull()?.playListId
?: -1,
songId
).isNotEmpty()
}
} }

View file

@ -207,11 +207,7 @@ class PlayingNotificationImpl(
override fun updateFavorite(song: Song, onUpdate: () -> Unit) { override fun updateFavorite(song: Song, onUpdate: () -> Unit) {
GlobalScope.launch(Dispatchers.IO) { GlobalScope.launch(Dispatchers.IO) {
val playlist: PlaylistEntity = MusicUtil.repository.favoritePlaylist() val isFavorite = MusicUtil.repository.isSongFavorite(song.id)
val isFavorite = if (playlist != null) {
val songEntity = song.toSongEntity(playlist.playListId)
MusicUtil.repository.isFavoriteSong(songEntity).isNotEmpty()
} else false
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
mActions[0] = buildFavoriteAction(isFavorite) mActions[0] = buildFavoriteAction(isFavorite)
onUpdate() onUpdate()