Playlist Add, Delete, Add Songs

This commit is contained in:
Hemanth S 2020-08-21 01:32:40 +05:30
parent 6aa9b08ff2
commit f3988ae1d1
51 changed files with 551 additions and 137 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View file

@ -55,9 +55,11 @@ object Constants {
} }
const val EXTRA_GENRE = "extra_genre" const val EXTRA_GENRE = "extra_genre"
const val EXTRA_PLAYLIST = "extra_playlist" const val EXTRA_PLAYLIST = "extra_playlist"
const val EXTRA_PLAYLIST_ID = "extra_playlist_id"
const val EXTRA_ALBUM_ID = "extra_album_id" const val EXTRA_ALBUM_ID = "extra_album_id"
const val EXTRA_ARTIST_ID = "extra_artist_id" const val EXTRA_ARTIST_ID = "extra_artist_id"
const val EXTRA_SONG = "extra_songs" const val EXTRA_SONG = "extra_songs"
const val EXTRA_PLAYLISTS = "extra_playlists"
const val LIBRARY_CATEGORIES = "library_categories" const val LIBRARY_CATEGORIES = "library_categories"
const val EXTRA_SONG_INFO = "extra_song_info" const val EXTRA_SONG_INFO = "extra_song_info"
const val DESATURATED_COLOR = "desaturated_color" const val DESATURATED_COLOR = "desaturated_color"

View file

@ -24,6 +24,7 @@ import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.db.SongEntity import code.name.monkey.retromusic.db.SongEntity
import code.name.monkey.retromusic.extensions.hide import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
import code.name.monkey.retromusic.interfaces.CabHolder import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Playlist import code.name.monkey.retromusic.model.Playlist
@ -45,7 +46,6 @@ class PlaylistAdapter(
R.menu.menu_playlists_selection R.menu.menu_playlists_selection
) { ) {
init { init {
setHasStableIds(true) setHasStableIds(true)
} }
@ -130,14 +130,14 @@ class PlaylistAdapter(
private fun getSongList(playlists: List<PlaylistWithSongs>): List<Song> { private fun getSongList(playlists: List<PlaylistWithSongs>): List<Song> {
val songs = ArrayList<Song>() val songs = ArrayList<Song>()
/* for (playlist in playlists) { /* for (playlist in playlists) {
songs.addAll(playlist.songs) songs.addAll(playlist.songs)
if (playlist is AbsCustomPlaylist) { if (playlist is AbsCustomPlaylist) {
songs.addAll(playlist.songs()) songs.addAll(playlist.songs())
} else { } else {
songs.addAll(PlaylistSongsLoader.getPlaylistSongList(activity, playlist.id)) songs.addAll(PlaylistSongsLoader.getPlaylistSongList(activity, playlist.id))
} }
}*/ }*/
return songs return songs
} }
@ -165,7 +165,7 @@ class PlaylistAdapter(
val popupMenu = PopupMenu(activity, view) val popupMenu = PopupMenu(activity, view)
popupMenu.inflate(R.menu.menu_item_playlist) popupMenu.inflate(R.menu.menu_item_playlist)
popupMenu.setOnMenuItemClickListener { item -> popupMenu.setOnMenuItemClickListener { item ->
return@setOnMenuItemClickListener true //PlaylistMenuHelper.handleMenuClick(activity, dataSet[layoutPosition], item) PlaylistMenuHelper.handleMenuClick(activity, dataSet[layoutPosition], item)
} }
popupMenu.show() popupMenu.show()
} }
@ -219,7 +219,5 @@ class PlaylistAdapter(
companion object { companion object {
val TAG: String = PlaylistAdapter::class.java.simpleName val TAG: String = PlaylistAdapter::class.java.simpleName
private const val SMART_PLAYLIST = 0
private const val DEFAULT_PLAYLIST = 1
} }
} }

View file

@ -6,6 +6,7 @@ import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.R.menu import code.name.monkey.retromusic.R.menu
import code.name.monkey.retromusic.dialogs.RemoveFromPlaylistDialog import code.name.monkey.retromusic.dialogs.RemoveFromPlaylistDialog
import code.name.monkey.retromusic.dialogs.RemoveSongFromPlaylistDialog
import code.name.monkey.retromusic.interfaces.CabHolder import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.PlaylistSong import code.name.monkey.retromusic.model.PlaylistSong
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
@ -16,6 +17,7 @@ import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange
import com.h6ah4i.android.widget.advrecyclerview.draggable.annotation.DraggableItemStateFlags import com.h6ah4i.android.widget.advrecyclerview.draggable.annotation.DraggableItemStateFlags
class OrderablePlaylistSongAdapter( class OrderablePlaylistSongAdapter(
private val playlistId: Int,
activity: FragmentActivity, activity: FragmentActivity,
dataSet: ArrayList<Song>, dataSet: ArrayList<Song>,
itemLayoutRes: Int, itemLayoutRes: Int,
@ -118,7 +120,7 @@ class OrderablePlaylistSongAdapter(
override fun onSongMenuItemClick(item: MenuItem): Boolean { override fun onSongMenuItemClick(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.action_remove_from_playlist -> { R.id.action_remove_from_playlist -> {
RemoveFromPlaylistDialog.create(song as PlaylistSong) RemoveSongFromPlaylistDialog.create( song.toSongEntity(playlistId))
.show(activity.supportFragmentManager, "REMOVE_FROM_PLAYLIST") .show(activity.supportFragmentManager, "REMOVE_FROM_PLAYLIST")
return true return true
} }

View file

@ -4,16 +4,21 @@ import androidx.room.*
@Dao @Dao
interface PlaylistDao { interface PlaylistDao {
@Insert
suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long
@Query("UPDATE PlaylistEntity SET playlist_name = :name WHERE playlist_id = :playlistId")
suspend fun renamePlaylistEntity(playlistId: Int, name: String)
@Query("SELECT * FROM PlaylistEntity WHERE playlist_name = :name") @Query("SELECT * FROM PlaylistEntity WHERE playlist_name = :name")
suspend fun checkPlaylistExists(name: String): List<PlaylistEntity> suspend fun checkPlaylistExists(name: String): List<PlaylistEntity>
@Insert
suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long
@Query("SELECT * FROM PlaylistEntity") @Query("SELECT * FROM PlaylistEntity")
suspend fun playlists(): List<PlaylistEntity> suspend fun playlists(): List<PlaylistEntity>
@Query("DELETE FROM SongEntity WHERE playlist_creator_id = :playlistId")
suspend fun deleteSongsFromPlaylist(playlistId: Int)
@Transaction @Transaction
@Query("SELECT * FROM PlaylistEntity") @Query("SELECT * FROM PlaylistEntity")
suspend fun playlistsWithSong(): List<PlaylistWithSongs> suspend fun playlistsWithSong(): List<PlaylistWithSongs>
@ -24,9 +29,16 @@ interface PlaylistDao {
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistName AND id = :songId") @Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistName AND id = :songId")
suspend fun checkSongExistsWithPlaylistName(playlistName: String, songId: Int): List<SongEntity> suspend fun checkSongExistsWithPlaylistName(playlistName: String, songId: Int): List<SongEntity>
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistId ORDER BY title") @Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistId")
suspend fun getSongs(playlistId: Int): List<SongEntity> suspend fun getSongs(playlistId: Int): List<SongEntity>
@Delete @Delete
suspend fun deletePlaylistEntity(playlistWithSongs: PlaylistWithSongs) suspend fun deletePlaylistEntity(playlistEntity: PlaylistEntity)
@Delete
suspend fun deletePlaylistEntities(playlistEntities: List<PlaylistEntity>)
@Delete
suspend fun removeSongsFromPlaylist(songs: List<SongEntity>)
} }

View file

@ -14,3 +14,4 @@ data class PlaylistWithSongs(
) )
val songs: List<SongEntity> val songs: List<SongEntity>
):Parcelable ):Parcelable

View file

@ -55,3 +55,9 @@ class SongEntity(
) )
} }
} }
fun List<SongEntity>.toSongs(): List<Song> {
return map {
it.toSong()
}
}

View file

@ -5,30 +5,46 @@ import android.os.Bundle
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.EXTRA_PLAYLISTS
import code.name.monkey.retromusic.EXTRA_SONG
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.db.PlaylistEntity import code.name.monkey.retromusic.db.PlaylistEntity
import code.name.monkey.retromusic.repository.RoomPlaylistRepository
import code.name.monkey.retromusic.db.SongEntity import code.name.monkey.retromusic.db.SongEntity
import code.name.monkey.retromusic.extensions.colorButtons import code.name.monkey.retromusic.extensions.colorButtons
import code.name.monkey.retromusic.extensions.extraNotNull import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.extensions.materialDialog import code.name.monkey.retromusic.extensions.materialDialog
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.ReloadType
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.repository.RealSongRepository import code.name.monkey.retromusic.repository.RealRepository
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.android.ext.android.get import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
class AddToRetroPlaylist : DialogFragment() { class AddToRetroPlaylist : DialogFragment() {
private val repository by inject<RealRepository>()
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
companion object { companion object {
fun getInstance(playlistName: List<PlaylistEntity>): AddToRetroPlaylist { fun create(playlistEntities: List<PlaylistEntity>, song: Song): AddToRetroPlaylist {
val list = mutableListOf<Song>()
list.add(song)
return create(playlistEntities, list)
}
fun create(playlistEntities: List<PlaylistEntity>, songs: List<Song>): AddToRetroPlaylist {
return AddToRetroPlaylist().apply { return AddToRetroPlaylist().apply {
arguments = bundleOf("playlist_names" to playlistName) arguments = bundleOf(
EXTRA_SONG to songs,
EXTRA_PLAYLISTS to playlistEntities
)
} }
} }
} }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val playlistEntities = extraNotNull<List<PlaylistEntity>>("playlist_names").value val playlistEntities = extraNotNull<List<PlaylistEntity>>(EXTRA_PLAYLISTS).value
val playlistNames = mutableListOf<String>() val playlistNames = mutableListOf<String>()
playlistNames.add(requireContext().resources.getString(R.string.action_new_playlist)) playlistNames.add(requireContext().resources.getString(R.string.action_new_playlist))
for (p in playlistEntities) { for (p in playlistEntities) {
@ -36,14 +52,14 @@ class AddToRetroPlaylist : DialogFragment() {
} }
return materialDialog(R.string.add_playlist_title) return materialDialog(R.string.add_playlist_title)
.setItems(playlistNames.toTypedArray()) { _, which -> .setItems(playlistNames.toTypedArray()) { _, which ->
val songs = RealSongRepository(requireContext()).songs() val songs = extraNotNull<List<Song>>(EXTRA_SONG).value
if (which == 0) { if (which == 0) {
CreateRetroPlaylist().show(requireActivity().supportFragmentManager, "Dialog") CreateRetroPlaylist().show(requireActivity().supportFragmentManager, "Dialog")
} else { } else {
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
val playlistRepository = get<RoomPlaylistRepository>()
val songEntities = songs.withPlaylistIds(playlistEntities[which - 1]) val songEntities = songs.withPlaylistIds(playlistEntities[which - 1])
playlistRepository.insertSongs(songEntities) repository.insertSongs(songEntities)
libraryViewModel.forceReload(ReloadType.Playlists)
} }
} }
dismiss() dismiss()

View file

@ -4,24 +4,26 @@ import android.app.Dialog
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils import android.text.TextUtils
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.Toast
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.db.PlaylistEntity import code.name.monkey.retromusic.db.PlaylistEntity
import code.name.monkey.retromusic.repository.RoomPlaylistRepository
import code.name.monkey.retromusic.extensions.colorButtons import code.name.monkey.retromusic.extensions.colorButtons
import code.name.monkey.retromusic.extensions.materialDialog import code.name.monkey.retromusic.extensions.materialDialog
import code.name.monkey.retromusic.fragments.LibraryViewModel import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.ReloadType import code.name.monkey.retromusic.fragments.ReloadType.Playlists
import code.name.monkey.retromusic.repository.RealRepository
import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import kotlinx.android.synthetic.main.dialog_playlist.view.* import kotlinx.android.synthetic.main.dialog_playlist.view.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.sharedViewModel import org.koin.androidx.viewmodel.ext.android.sharedViewModel
class CreateRetroPlaylist : DialogFragment() { class CreateRetroPlaylist : DialogFragment() {
private val playlistRepository by inject<RoomPlaylistRepository>() private val repository by inject<RealRepository>()
private val libraryViewModel by sharedViewModel<LibraryViewModel>() private val libraryViewModel by sharedViewModel<LibraryViewModel>()
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val view = LayoutInflater.from(requireActivity()).inflate(R.layout.dialog_playlist, null) val view = LayoutInflater.from(requireActivity()).inflate(R.layout.dialog_playlist, null)
@ -34,14 +36,13 @@ class CreateRetroPlaylist : DialogFragment() {
) { _, _ -> ) { _, _ ->
val playlistName = playlistView.text.toString() val playlistName = playlistView.text.toString()
if (!TextUtils.isEmpty(playlistName)) { if (!TextUtils.isEmpty(playlistName)) {
lifecycleScope.launch { lifecycleScope.launch(Dispatchers.IO) {
if (playlistRepository.checkPlaylistExists(playlistName).isEmpty()) { if (repository.checkPlaylistExists(playlistName).isEmpty()) {
val id: Long = repository.createPlaylist(PlaylistEntity(playlistName))
playlistRepository.createPlaylist(PlaylistEntity(playlistName)) libraryViewModel.forceReload(Playlists)
println(id)
libraryViewModel.forceReload(ReloadType.Playlists)
} else { } else {
println("Playlist exists") Toast.makeText(requireContext(), "Playlist exists", Toast.LENGTH_SHORT)
.show()
} }
} }

View file

@ -0,0 +1,76 @@
package code.name.monkey.retromusic.dialogs
import android.app.Dialog
import android.os.Bundle
import androidx.core.os.bundleOf
import androidx.core.text.HtmlCompat
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.EXTRA_PLAYLIST
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.db.PlaylistEntity
import code.name.monkey.retromusic.extensions.colorButtons
import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.extensions.materialDialog
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.ReloadType
import code.name.monkey.retromusic.repository.Repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
class DeleteRetroPlaylist : DialogFragment() {
private val repository by inject<Repository>()
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
companion object {
fun create(playlist: PlaylistEntity): DeleteRetroPlaylist {
val list = mutableListOf<PlaylistEntity>()
list.add(playlist)
return create(list)
}
fun create(playlists: List<PlaylistEntity>): DeleteRetroPlaylist {
return DeleteRetroPlaylist().apply {
arguments = bundleOf(EXTRA_PLAYLIST to playlists)
}
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val playlists = extraNotNull<List<PlaylistEntity>>(EXTRA_PLAYLIST).value
val title: Int
val message: CharSequence
//noinspection ConstantConditions
if (playlists.size > 1) {
title = R.string.delete_playlists_title
message = HtmlCompat.fromHtml(
String.format(getString(R.string.delete_x_playlists), playlists.size),
HtmlCompat.FROM_HTML_MODE_LEGACY
)
} else {
title = R.string.delete_playlist_title
message = HtmlCompat.fromHtml(
String.format(getString(R.string.delete_playlist_x), playlists[0].playlistName),
HtmlCompat.FROM_HTML_MODE_LEGACY
)
}
return materialDialog(title)
.setTitle(title)
.setMessage(message)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.action_delete) { _, _ ->
lifecycleScope.launch(Dispatchers.IO) {
repository.deleteSongsFromPlaylist(playlists)
repository.deleteRoomPlaylist(playlists)
libraryViewModel.forceReload(ReloadType.Playlists)
}
}
.create()
.colorButtons()
}
}

View file

@ -0,0 +1,79 @@
package code.name.monkey.retromusic.dialogs
import android.app.Dialog
import android.os.Bundle
import androidx.core.os.bundleOf
import androidx.core.text.HtmlCompat
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.EXTRA_SONG
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.db.SongEntity
import code.name.monkey.retromusic.extensions.colorButtons
import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.extensions.materialDialog
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.repository.Repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
class RemoveSongFromPlaylistDialog : DialogFragment() {
private val repository by inject<Repository>()
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
companion object {
fun create(song: SongEntity): RemoveSongFromPlaylistDialog {
val list = mutableListOf<SongEntity>()
list.add(song)
return create(list)
}
fun create(songs: List<SongEntity>): RemoveSongFromPlaylistDialog {
return RemoveSongFromPlaylistDialog().apply {
arguments = bundleOf(
EXTRA_SONG to songs
)
}
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val songs = extraNotNull<List<SongEntity>>(EXTRA_SONG).value
val pair = if (songs.size > 1) {
Pair(
R.string.remove_songs_from_playlist_title,
HtmlCompat.fromHtml(
String.format(getString(R.string.remove_x_songs_from_playlist), songs.size),
HtmlCompat.FROM_HTML_MODE_LEGACY
)
)
} else {
Pair(
R.string.remove_song_from_playlist_title,
HtmlCompat.fromHtml(
String.format(
getString(R.string.remove_song_x_from_playlist),
songs[0].title
),
HtmlCompat.FROM_HTML_MODE_LEGACY
)
)
}
return materialDialog(pair.first)
.setMessage(pair.second)
.setPositiveButton(R.string.remove_action) { _, _ ->
lifecycleScope.launch(Dispatchers.IO) {
repository.removeSongFromPlaylist(songs)
}
/* PlaylistsUtil.removeFromPlaylist(
requireContext(),
songs as MutableList<PlaylistSong>
)*/
}
.setNegativeButton(android.R.string.cancel, null)
.create()
.colorButtons()
}
}

View file

@ -0,0 +1,64 @@
package code.name.monkey.retromusic.dialogs
import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import androidx.core.os.bundleOf
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.EXTRA_PLAYLIST_ID
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.db.PlaylistEntity
import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.colorButtons
import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.extensions.materialDialog
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.ReloadType
import code.name.monkey.retromusic.repository.Repository
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
class RenameRetroPlaylistDialog : DialogFragment() {
private val repository by inject<Repository>()
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
companion object {
fun create(playlistEntity: PlaylistEntity): RenameRetroPlaylistDialog {
return RenameRetroPlaylistDialog().apply {
arguments = bundleOf(
EXTRA_PLAYLIST_ID to playlistEntity
)
}
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val playlistEntity = extraNotNull<PlaylistEntity>(EXTRA_PLAYLIST_ID).value
val layout = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_playlist, null)
val inputEditText: TextInputEditText = layout.findViewById(R.id.actionNewPlaylist)
val nameContainer: TextInputLayout = layout.findViewById(R.id.actionNewPlaylistContainer)
nameContainer.accentColor()
inputEditText.setText(playlistEntity.playlistName)
return materialDialog(R.string.rename_playlist_title)
.setView(layout)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.action_rename) { _, _ ->
val name = inputEditText.text.toString()
if (name.isNotEmpty()) {
lifecycleScope.launch(Dispatchers.IO) {
repository.renameRoomPlaylist(playlistEntity.playListId, name)
libraryViewModel.forceReload(ReloadType.Playlists)
}
} else {
nameContainer.error = "Playlist name should'nt be empty"
}
}
.create()
.colorButtons()
}
}

View file

@ -34,6 +34,7 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
mainActivity.setSupportActionBar(toolbar) mainActivity.setSupportActionBar(toolbar)
mainActivity.hideBottomBarVisibility(false) mainActivity.hideBottomBarVisibility(false)
progressIndicator.hide()
when (args.type) { when (args.type) {
TOP_ARTISTS -> { TOP_ARTISTS -> {
loadArtists(R.string.top_artists, TOP_ARTISTS) loadArtists(R.string.top_artists, TOP_ARTISTS)

View file

@ -33,7 +33,7 @@ class LibraryViewModel(
val songsLiveData: LiveData<List<Song>> = songs val songsLiveData: LiveData<List<Song>> = songs
val artistsLiveData: LiveData<List<Artist>> = artists val artistsLiveData: LiveData<List<Artist>> = artists
val playlisitsLiveData: LiveData<List<Playlist>> = playlists val playlisitsLiveData: LiveData<List<Playlist>> = playlists
val roomPlaylisitsLiveData: LiveData<List<PlaylistWithSongs>> = roomPlaylists val roomPlaylistsLiveData: LiveData<List<PlaylistWithSongs>> = roomPlaylists
val genresLiveData: LiveData<List<Genre>> = genres val genresLiveData: LiveData<List<Genre>> = genres
init { init {
@ -43,13 +43,13 @@ class LibraryViewModel(
} }
private fun loadLibraryContent() = viewModelScope.launch { private fun loadLibraryContent() = viewModelScope.launch {
home.value = loadHome.await()
songs.value = loadSongs.await() songs.value = loadSongs.await()
albums.value = loadAlbums.await() albums.value = loadAlbums.await()
artists.value = loadArtists.await() artists.value = loadArtists.await()
playlists.value = loadPlaylists.await() playlists.value = loadPlaylists.await()
roomPlaylists.value = loadPlaylistsWithSongs.await() roomPlaylists.value = loadPlaylistsWithSongs.await()
//genres.value = loadGenres.await() //genres.value = loadGenres.await()
home.value = loadHome.await()
} }
private val loadHome: Deferred<List<Home>> private val loadHome: Deferred<List<Home>>
@ -84,6 +84,7 @@ class LibraryViewModel(
fun forceReload(reloadType: ReloadType) = viewModelScope.launch { fun forceReload(reloadType: ReloadType) = viewModelScope.launch {
println(reloadType)
when (reloadType) { when (reloadType) {
Songs -> songs.value = loadSongs.await() Songs -> songs.value = loadSongs.await()
Albums -> albums.value = loadAlbums.await() Albums -> albums.value = loadAlbums.await()

View file

@ -7,6 +7,7 @@ import android.view.*
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
@ -22,7 +23,7 @@ import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity
import code.name.monkey.retromusic.activities.tageditor.AlbumTagEditorActivity import code.name.monkey.retromusic.activities.tageditor.AlbumTagEditorActivity
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog import code.name.monkey.retromusic.dialogs.AddToRetroPlaylist
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
import code.name.monkey.retromusic.extensions.applyColor import code.name.monkey.retromusic.extensions.applyColor
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
@ -35,6 +36,7 @@ import code.name.monkey.retromusic.helper.SortOrder
import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.network.model.LastFmAlbum import code.name.monkey.retromusic.network.model.LastFmAlbum
import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.RetroUtil import code.name.monkey.retromusic.util.RetroUtil
@ -42,6 +44,10 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.fragment_album_content.* import kotlinx.android.synthetic.main.fragment_album_content.*
import kotlinx.android.synthetic.main.fragment_album_details.* import kotlinx.android.synthetic.main.fragment_album_details.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.android.ext.android.get
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf import org.koin.core.parameter.parametersOf
import java.util.* import java.util.*
@ -275,7 +281,13 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
return true return true
} }
R.id.action_add_to_playlist -> { R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(songs).show(childFragmentManager, "ADD_PLAYLIST") lifecycleScope.launch(Dispatchers.IO) {
val playlists = get<RealRepository>().roomPlaylists()
withContext(Dispatchers.Main) {
AddToRetroPlaylist.create(playlists, songs)
.show(childFragmentManager, "ADD_PLAYLIST")
}
}
return true return true
} }
R.id.action_delete_from_device -> { R.id.action_delete_from_device -> {

View file

@ -10,6 +10,7 @@ import android.view.View
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.text.HtmlCompat import androidx.core.text.HtmlCompat
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.FragmentNavigatorExtras import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
@ -19,7 +20,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog import code.name.monkey.retromusic.dialogs.AddToRetroPlaylist
import code.name.monkey.retromusic.extensions.applyColor import code.name.monkey.retromusic.extensions.applyColor
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.extensions.showToast import code.name.monkey.retromusic.extensions.showToast
@ -30,6 +31,7 @@ import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.network.model.LastFmArtist import code.name.monkey.retromusic.network.model.LastFmArtist
import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.util.CustomArtistImageUtil import code.name.monkey.retromusic.util.CustomArtistImageUtil
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.RetroUtil import code.name.monkey.retromusic.util.RetroUtil
@ -37,6 +39,10 @@ import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.fragment_artist_content.* import kotlinx.android.synthetic.main.fragment_artist_content.*
import kotlinx.android.synthetic.main.fragment_artist_details.* import kotlinx.android.synthetic.main.fragment_artist_details.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.android.ext.android.get
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf import org.koin.core.parameter.parametersOf
import java.util.* import java.util.*
@ -216,7 +222,13 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d
return true return true
} }
R.id.action_add_to_playlist -> { R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(songs).show(childFragmentManager, "ADD_PLAYLIST") lifecycleScope.launch(Dispatchers.IO) {
val playlists = get<RealRepository>().roomPlaylists()
withContext(Dispatchers.Main) {
AddToRetroPlaylist.create(playlists, songs)
.show(childFragmentManager, "ADD_PLAYLIST")
}
}
return true return true
} }
R.id.action_set_artist_image -> { R.id.action_set_artist_image -> {

View file

@ -15,6 +15,7 @@ import android.widget.Toast
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController import androidx.navigation.findNavController
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
@ -29,8 +30,13 @@ import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.PaletteColorHolder import code.name.monkey.retromusic.interfaces.PaletteColorHolder
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.model.lyrics.Lyrics import code.name.monkey.retromusic.model.lyrics.Lyrics
import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.util.* import code.name.monkey.retromusic.util.*
import kotlinx.android.synthetic.main.shadow_statusbar_toolbar.* import kotlinx.android.synthetic.main.shadow_statusbar_toolbar.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.android.ext.android.get
import org.koin.androidx.viewmodel.ext.android.sharedViewModel import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import java.io.FileNotFoundException import java.io.FileNotFoundException
@ -64,7 +70,13 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
return true return true
} }
R.id.action_add_to_playlist -> { R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(song).show(childFragmentManager, "ADD_PLAYLIST") lifecycleScope.launch(Dispatchers.IO) {
val playlists = get<RealRepository>().roomPlaylists()
withContext(Dispatchers.Main) {
AddToRetroPlaylist.create(playlists, song)
.show(childFragmentManager, "ADD_PLAYLIST")
}
}
return true return true
} }
R.id.action_clear_playing_queue -> { R.id.action_clear_playing_queue -> {

View file

@ -4,20 +4,15 @@ import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.NavigationUI import androidx.navigation.ui.NavigationUI
import code.name.monkey.appthemehelper.common.ATHToolbarActivity.getToolbarBackgroundColor import code.name.monkey.appthemehelper.common.ATHToolbarActivity.getToolbarBackgroundColor
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.repository.RoomPlaylistRepository import code.name.monkey.retromusic.dialogs.CreateRetroPlaylist
import code.name.monkey.retromusic.dialogs.AddToRetroPlaylist
import code.name.monkey.retromusic.extensions.findNavController import code.name.monkey.retromusic.extensions.findNavController
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import com.google.android.material.appbar.AppBarLayout
import kotlinx.android.synthetic.main.fragment_library.* import kotlinx.android.synthetic.main.fragment_library.*
import kotlinx.coroutines.launch
import org.koin.android.ext.android.get
class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) { class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
@ -34,12 +29,29 @@ class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
navOptions navOptions
) )
} }
addPlaylist.setOnClickListener {
CreateRetroPlaylist().show(childFragmentManager, "ShowCreatePlaylistDialog")
}
setupNavigationController() setupNavigationController()
} }
private fun setupNavigationController() { private fun setupNavigationController() {
val navController = findNavController(R.id.fragment_container) val navController = findNavController(R.id.fragment_container)
NavigationUI.setupWithNavController(mainActivity.getBottomNavigationView(), navController) NavigationUI.setupWithNavController(mainActivity.getBottomNavigationView(), navController)
navController.addOnDestinationChangedListener { _, destination, _ ->
if (destination.id in arrayOf(
R.id.action_album,
R.id.action_artist,
R.id.action_home,
R.id.action_song,
R.id.action_genre
)
) {
addPlaylist.hide()
} else {
addPlaylist.show()
}
}
} }
override fun onPrepareOptionsMenu(menu: Menu) { override fun onPrepareOptionsMenu(menu: Menu) {
@ -60,32 +72,12 @@ class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.action_settings -> R.id.action_settings -> findNavController().navigate(
//CreateRetroPlaylist().show(childFragmentManager, "Dialog") R.id.settingsActivity,
lifecycleScope.launch { null,
val playlistRepository = get<RoomPlaylistRepository>() navOptions
AddToRetroPlaylist.getInstance(playlistRepository.playlists()) )
.show(childFragmentManager, "PlaylistDialog")
}
/*findNavController().navigate(
R.id.settingsActivity,
null,
navOptions
)*/
} }
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)
} }
fun addOnAppBarOffsetChangedListener(changedListener: AppBarLayout.OnOffsetChangedListener) {
appBarLayout.addOnOffsetChangedListener(changedListener)
}
fun removeOnAppBarOffsetChangedListener(changedListener: AppBarLayout.OnOffsetChangedListener) {
appBarLayout.removeOnOffsetChangedListener(changedListener)
}
fun getTotalAppBarScrollingRange(): Int {
return 0
}
} }

View file

@ -15,6 +15,7 @@ import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.db.PlaylistWithSongs import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.extensions.dipToPix import code.name.monkey.retromusic.extensions.dipToPix
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.PlaylistsUtil import code.name.monkey.retromusic.util.PlaylistsUtil
import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator
@ -61,25 +62,28 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
} else {*/ } else {*/
recyclerViewDragDropManager = RecyclerViewDragDropManager() recyclerViewDragDropManager = RecyclerViewDragDropManager()
val animator = RefactoredDefaultItemAnimator() val animator = RefactoredDefaultItemAnimator()
adapter = OrderablePlaylistSongAdapter(requireActivity(), adapter =
ArrayList(), OrderablePlaylistSongAdapter(
R.layout.item_list, playlist.playlistEntity.playListId,
null, requireActivity(),
object : OrderablePlaylistSongAdapter.OnMoveItemListener { ArrayList(),
override fun onMoveItem(fromPosition: Int, toPosition: Int) { R.layout.item_list,
if (PlaylistsUtil.moveItem( null,
requireContext(), object : OrderablePlaylistSongAdapter.OnMoveItemListener {
playlist.playlistEntity.playListId, override fun onMoveItem(fromPosition: Int, toPosition: Int) {
fromPosition, if (PlaylistsUtil.moveItem(
toPosition requireContext(),
) playlist.playlistEntity.playListId,
) { fromPosition,
val song = adapter.dataSet.removeAt(fromPosition) toPosition
adapter.dataSet.add(toPosition, song) )
adapter.notifyItemMoved(fromPosition, toPosition) ) {
val song = adapter.dataSet.removeAt(fromPosition)
adapter.dataSet.add(toPosition, song)
adapter.notifyItemMoved(fromPosition, toPosition)
}
} }
} })
})
wrappedAdapter = recyclerViewDragDropManager!!.createWrappedAdapter(adapter) wrappedAdapter = recyclerViewDragDropManager!!.createWrappedAdapter(adapter)
recyclerView.adapter = wrappedAdapter recyclerView.adapter = wrappedAdapter
@ -104,7 +108,7 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
return true//PlaylistMenuHelper.handleMenuClick(requireActivity(), playlist, item) return PlaylistMenuHelper.handleMenuClick(requireActivity(), playlist, item)
} }
private fun checkForPadding() { private fun checkForPadding() {

View file

@ -19,7 +19,7 @@ class PlaylistsFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
libraryViewModel.roomPlaylisitsLiveData.observe(viewLifecycleOwner, Observer { libraryViewModel.roomPlaylistsLiveData.observe(viewLifecycleOwner, Observer {
if (it.isNotEmpty()) if (it.isNotEmpty())
adapter?.swapDataSet(it) adapter?.swapDataSet(it)
else else

View file

@ -19,12 +19,16 @@ import android.view.View
import androidx.preference.Preference import androidx.preference.Preference
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEListPreference import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEListPreference
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.ReloadType.HomeSections
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
/** /**
* @author Hemanth S (h4h13). * @author Hemanth S (h4h13).
*/ */
class OtherSettingsFragment : AbsSettingsFragment() { class OtherSettingsFragment : AbsSettingsFragment() {
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
override fun invalidateSettings() { override fun invalidateSettings() {
val languagePreference: ATEListPreference? = findPreference("language_name") val languagePreference: ATEListPreference? = findPreference("language_name")
languagePreference?.setOnPreferenceChangeListener { _, _ -> languagePreference?.setOnPreferenceChangeListener { _, _ ->
@ -42,6 +46,7 @@ class OtherSettingsFragment : AbsSettingsFragment() {
val preference: Preference? = findPreference("last_added_interval") val preference: Preference? = findPreference("last_added_interval")
preference?.setOnPreferenceChangeListener { lastAdded, newValue -> preference?.setOnPreferenceChangeListener { lastAdded, newValue ->
setSummary(lastAdded, newValue) setSummary(lastAdded, newValue)
libraryViewModel.forceReload(HomeSections)
true true
} }
val languagePreference: Preference? = findPreference("language_name") val languagePreference: Preference? = findPreference("language_name")

View file

@ -17,12 +17,18 @@ package code.name.monkey.retromusic.helper.menu
import android.view.MenuItem import android.view.MenuItem
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog import code.name.monkey.retromusic.dialogs.AddToRetroPlaylist
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Genre import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.repository.GenreRepository import code.name.monkey.retromusic.repository.GenreRepository
import code.name.monkey.retromusic.repository.RealRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.core.KoinComponent import org.koin.core.KoinComponent
import org.koin.core.get
import org.koin.core.inject import org.koin.core.inject
object GenreMenuHelper : KoinComponent { object GenreMenuHelper : KoinComponent {
@ -38,8 +44,13 @@ object GenreMenuHelper : KoinComponent {
return true return true
} }
R.id.action_add_to_playlist -> { R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(getGenreSongs(genre)) CoroutineScope(Dispatchers.IO).launch {
.show(activity.supportFragmentManager, "ADD_PLAYLIST") val playlists = get<RealRepository>().roomPlaylists()
withContext(Dispatchers.Main) {
AddToRetroPlaylist.create(playlists, getGenreSongs(genre))
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
}
}
return true return true
} }
R.id.action_add_to_current_playing -> { R.id.action_add_to_current_playing -> {

View file

@ -22,53 +22,67 @@ import android.widget.Toast
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.App import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.dialogs.DeletePlaylistDialog import code.name.monkey.retromusic.db.toSongs
import code.name.monkey.retromusic.dialogs.RenamePlaylistDialog import code.name.monkey.retromusic.dialogs.AddToRetroPlaylist
import code.name.monkey.retromusic.dialogs.DeleteRetroPlaylist
import code.name.monkey.retromusic.dialogs.RenameRetroPlaylistDialog
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.misc.WeakContextAsyncTask import code.name.monkey.retromusic.misc.WeakContextAsyncTask
import code.name.monkey.retromusic.model.AbsCustomPlaylist import code.name.monkey.retromusic.model.AbsCustomPlaylist
import code.name.monkey.retromusic.model.Playlist import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.util.PlaylistsUtil import code.name.monkey.retromusic.util.PlaylistsUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.core.KoinComponent
import org.koin.core.get
object PlaylistMenuHelper { object PlaylistMenuHelper : KoinComponent {
fun handleMenuClick( fun handleMenuClick(
activity: FragmentActivity, activity: FragmentActivity,
playlist: Playlist, item: MenuItem playlistWithSongs: PlaylistWithSongs, item: MenuItem
): Boolean { ): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.action_play -> { R.id.action_play -> {
MusicPlayerRemote.openQueue(getPlaylistSongs(activity, playlist), 9, true) MusicPlayerRemote.openQueue(playlistWithSongs.songs.toSongs(), 0, true)
return true return true
} }
R.id.action_play_next -> { R.id.action_play_next -> {
MusicPlayerRemote.playNext(getPlaylistSongs(activity, playlist)) MusicPlayerRemote.playNext(playlistWithSongs.songs.toSongs())
return true return true
} }
R.id.action_add_to_playlist -> { R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(getPlaylistSongs(activity, playlist)) CoroutineScope(Dispatchers.IO).launch {
.show(activity.supportFragmentManager, "ADD_PLAYLIST") val playlists = get<RealRepository>().roomPlaylists()
withContext(Dispatchers.Main) {
AddToRetroPlaylist.create(playlists, playlistWithSongs.songs.toSongs())
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
}
}
return true return true
} }
R.id.action_add_to_current_playing -> { R.id.action_add_to_current_playing -> {
MusicPlayerRemote.enqueue(getPlaylistSongs(activity, playlist)) MusicPlayerRemote.enqueue(playlistWithSongs.songs.toSongs())
return true return true
} }
R.id.action_rename_playlist -> { R.id.action_rename_playlist -> {
RenamePlaylistDialog.create(playlist.id.toLong()) RenameRetroPlaylistDialog.create(playlistWithSongs.playlistEntity )
.show(activity.supportFragmentManager, "RENAME_PLAYLIST") .show(activity.supportFragmentManager, "RENAME_PLAYLIST")
return true return true
} }
R.id.action_delete_playlist -> { R.id.action_delete_playlist -> {
DeletePlaylistDialog.create(playlist) DeleteRetroPlaylist.create(playlistWithSongs.playlistEntity)
.show(activity.supportFragmentManager, "DELETE_PLAYLIST") .show(activity.supportFragmentManager, "DELETE_PLAYLIST")
return true return true
} }
R.id.action_save_playlist -> { R.id.action_save_playlist -> {
SavePlaylistAsyncTask(activity).execute(playlist) //SavePlaylistAsyncTask(activity).execute(playlistWithSongs.songs.toSongs())
return true return true
} }
} }

View file

@ -26,16 +26,23 @@ import code.name.monkey.retromusic.EXTRA_ARTIST_ID
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity
import code.name.monkey.retromusic.activities.tageditor.SongTagEditorActivity import code.name.monkey.retromusic.activities.tageditor.SongTagEditorActivity
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog import code.name.monkey.retromusic.dialogs.AddToRetroPlaylist
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
import code.name.monkey.retromusic.dialogs.SongDetailDialog import code.name.monkey.retromusic.dialogs.SongDetailDialog
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.PaletteColorHolder import code.name.monkey.retromusic.interfaces.PaletteColorHolder
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.RingtoneManager import code.name.monkey.retromusic.util.RingtoneManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.core.KoinComponent
import org.koin.core.get
object SongMenuHelper { object SongMenuHelper : KoinComponent {
const val MENU_RES = R.menu.menu_item_song const val MENU_RES = R.menu.menu_item_song
fun handleMenuClick(activity: FragmentActivity, song: Song, menuItemId: Int): Boolean { fun handleMenuClick(activity: FragmentActivity, song: Song, menuItemId: Int): Boolean {
@ -63,8 +70,13 @@ object SongMenuHelper {
return true return true
} }
R.id.action_add_to_playlist -> { R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(song) CoroutineScope(Dispatchers.IO).launch {
.show(activity.supportFragmentManager, "ADD_PLAYLIST") val playlists = get<RealRepository>().roomPlaylists()
withContext(Dispatchers.Main) {
AddToRetroPlaylist.create(playlists, song)
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
}
}
return true return true
} }
R.id.action_play_next -> { R.id.action_play_next -> {

View file

@ -16,13 +16,19 @@ package code.name.monkey.retromusic.helper.menu
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog import code.name.monkey.retromusic.dialogs.AddToRetroPlaylist
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.repository.RealRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.core.KoinComponent
import org.koin.core.get
object SongsMenuHelper : KoinComponent {
object SongsMenuHelper {
fun handleMenuClick( fun handleMenuClick(
activity: FragmentActivity, activity: FragmentActivity,
songs: List<Song>, songs: List<Song>,
@ -38,8 +44,13 @@ object SongsMenuHelper {
return true return true
} }
R.id.action_add_to_playlist -> { R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(songs) CoroutineScope(Dispatchers.IO).launch {
.show(activity.supportFragmentManager, "ADD_PLAYLIST") val playlists = get<RealRepository>().roomPlaylists()
withContext(Dispatchers.Main) {
AddToRetroPlaylist.create(playlists, songs)
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
}
}
return true return true
} }
R.id.action_delete_from_device -> { R.id.action_delete_from_device -> {

View file

@ -16,7 +16,9 @@ package code.name.monkey.retromusic.repository
import android.content.Context import android.content.Context
import code.name.monkey.retromusic.* import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.db.PlaylistEntity
import code.name.monkey.retromusic.db.PlaylistWithSongs import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.db.SongEntity
import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.model.*
import code.name.monkey.retromusic.model.smartplaylist.NotPlayedPlaylist import code.name.monkey.retromusic.model.smartplaylist.NotPlayedPlaylist
import code.name.monkey.retromusic.network.LastFMService import code.name.monkey.retromusic.network.LastFMService
@ -29,6 +31,17 @@ import kotlinx.coroutines.flow.flow
interface Repository { interface Repository {
fun songsFlow(): Flow<Result<List<Song>>>
fun albumsFlow(): Flow<Result<List<Album>>>
fun artistsFlow(): Flow<Result<List<Artist>>>
fun playlistsFlow(): Flow<Result<List<Playlist>>>
fun genresFlow(): Flow<Result<List<Genre>>>
suspend fun allAlbums(): List<Album> suspend fun allAlbums(): List<Album>
suspend fun albumById(albumId: Int): Album suspend fun albumById(albumId: Int): Album
@ -89,16 +102,21 @@ interface Repository {
suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs): List<Song> suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs): List<Song>
fun songsFlow(): Flow<Result<List<Song>>> suspend fun insertSongs(songs: List<SongEntity>)
fun albumsFlow(): Flow<Result<List<Album>>> suspend fun checkPlaylistExists(playlistName: String): List<PlaylistEntity>
fun artistsFlow(): Flow<Result<List<Artist>>> suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long
fun playlistsFlow(): Flow<Result<List<Playlist>>> suspend fun roomPlaylists(): List<PlaylistEntity>
fun genresFlow(): Flow<Result<List<Genre>>> suspend fun deleteRoomPlaylist(playlists: List<PlaylistEntity>)
suspend fun renameRoomPlaylist(playlistId: Int, name: String)
suspend fun removeSongFromPlaylist(songs: List<SongEntity>)
suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>)
} }
class RealRepository( class RealRepository(
@ -206,7 +224,6 @@ class RealRepository(
) )
for (section in sections) { for (section in sections) {
if (section.arrayList.isNotEmpty()) { if (section.arrayList.isNotEmpty()) {
println("${section.homeSection} -> ${section.arrayList.size}")
homeSections.add(section) homeSections.add(section)
} }
} }
@ -224,12 +241,35 @@ class RealRepository(
override suspend fun playlistWithSongs(): List<PlaylistWithSongs> = override suspend fun playlistWithSongs(): List<PlaylistWithSongs> =
roomPlaylistRepository.playlistWithSongs() roomPlaylistRepository.playlistWithSongs()
override suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs ): List<Song> { override suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs): List<Song> {
return playlistWithSongs.songs.map { return playlistWithSongs.songs.map {
it.toSong() it.toSong()
} }
} }
override suspend fun insertSongs(songs: List<SongEntity>) =
roomPlaylistRepository.insertSongs(songs)
override suspend fun checkPlaylistExists(playlistName: String): List<PlaylistEntity> =
roomPlaylistRepository.checkPlaylistExists(playlistName)
override suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long =
roomPlaylistRepository.createPlaylist(playlistEntity)
override suspend fun roomPlaylists(): List<PlaylistEntity> = roomPlaylistRepository.playlists()
override suspend fun deleteRoomPlaylist(playlists: List<PlaylistEntity>) =
roomPlaylistRepository.deletePlaylistEntities(playlists)
override suspend fun renameRoomPlaylist(playlistId: Int, name: String) =
roomPlaylistRepository.renamePlaylistEntity(playlistId, name)
override suspend fun removeSongFromPlaylist(songs: List<SongEntity>) =
roomPlaylistRepository.removeSongsFromPlaylist(songs)
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) =
roomPlaylistRepository.deleteSongsFromPlaylist(playlists)
override suspend fun suggestionsHome(): Home { override suspend fun suggestionsHome(): Home {
val songs = val songs =
NotPlayedPlaylist().songs().shuffled().takeIf { NotPlayedPlaylist().songs().shuffled().takeIf {

View file

@ -14,9 +14,15 @@ interface RoomPlaylistRepository {
suspend fun playlistWithSongs(): List<PlaylistWithSongs> suspend fun playlistWithSongs(): List<PlaylistWithSongs>
suspend fun insertSongs(songs: List<SongEntity>) suspend fun insertSongs(songs: List<SongEntity>)
suspend fun getSongs(playlistEntity: PlaylistEntity): List<SongEntity> suspend fun getSongs(playlistEntity: PlaylistEntity): List<SongEntity>
suspend fun deletePlaylistEntities(playlistEntities: List<PlaylistEntity>)
suspend fun renamePlaylistEntity(playlistId: Int, name: String)
suspend fun removeSongsFromPlaylist(songs: List<SongEntity>)
suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>)
} }
class RealRoomPlaylistRepository(private val playlistDao: PlaylistDao) : RoomPlaylistRepository { class RealRoomPlaylistRepository(
private val playlistDao: PlaylistDao
) : RoomPlaylistRepository {
@WorkerThread @WorkerThread
override suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long = override suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long =
playlistDao.createPlaylist(playlistEntity) playlistDao.createPlaylist(playlistEntity)
@ -46,4 +52,20 @@ class RealRoomPlaylistRepository(private val playlistDao: PlaylistDao) : RoomPla
override suspend fun getSongs(playlistEntity: PlaylistEntity): List<SongEntity> { override suspend fun getSongs(playlistEntity: PlaylistEntity): List<SongEntity> {
return playlistDao.getSongs(playlistEntity.playListId) return playlistDao.getSongs(playlistEntity.playListId)
} }
override suspend fun deletePlaylistEntities(playlistEntities: List<PlaylistEntity>) =
playlistDao.deletePlaylistEntities(playlistEntities)
override suspend fun renamePlaylistEntity(playlistId: Int, name: String) =
playlistDao.renamePlaylistEntity(playlistId, name)
override suspend fun removeSongsFromPlaylist(songs: List<SongEntity>) =
playlistDao.removeSongsFromPlaylist(songs)
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) {
playlists.forEach {
playlistDao.deleteSongsFromPlaylist(it.playListId)
}
}
} }

View file

@ -19,7 +19,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.widget.Toast
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.play.core.review.ReviewManagerFactory import com.google.android.play.core.review.ReviewManagerFactory
@ -71,8 +70,7 @@ object AppRater {
val reviewInfo = request.result val reviewInfo = request.result
manager.launchReviewFlow(context as Activity, reviewInfo).addOnCompleteListener { manager.launchReviewFlow(context as Activity, reviewInfo).addOnCompleteListener {
if (it.isSuccessful) { if (it.isSuccessful) {
Toast.makeText(context, "Thanks for the feedback", Toast.LENGTH_SHORT) //Toast.makeText(context, "Thanks for the feedback", Toast.LENGTH_SHORT).show()
.show()
} }
} }
} }

View file

@ -32,8 +32,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:text="@string/app_name" android:text="@string/app_name"
android:textStyle="bold" android:textAppearance="@style/TextViewHeadline6"
android:textAppearance="@style/TextViewHeadline6" /> android:textStyle="bold" />
</androidx.appcompat.widget.Toolbar> </androidx.appcompat.widget.Toolbar>
<ViewStub <ViewStub
@ -43,6 +43,16 @@
</FrameLayout> </FrameLayout>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="72dp"
android:layout_marginEnd="16dp"
android:id="@+id/addPlaylist"
android:src="@drawable/ic_playlist_add"
app:useCompatPadding="true" />
<androidx.fragment.app.FragmentContainerView <androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container" android:id="@+id/fragment_container"
android:name="androidx.navigation.fragment.NavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment"

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/> <background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/> <background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 24 KiB