Add save playlist 💾

This commit is contained in:
Hemanth S 2020-09-06 00:21:44 +05:30
parent 41e8aa8a03
commit 6e8ff6ab71
7 changed files with 105 additions and 60 deletions

View file

@ -87,3 +87,9 @@ fun Song.toPlayCount(): PlayCountEntity {
1 1
) )
} }
fun List<Song>.toSongsEntity(playlistEntity: PlaylistEntity): List<SongEntity> {
return map {
it.toSongEntity(playlistEntity.playListId)
}
}

View file

@ -3,29 +3,30 @@ package code.name.monkey.retromusic.dialogs
import android.app.Dialog import android.app.Dialog
import android.os.Bundle import android.os.Bundle
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
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_PLAYLISTS
import code.name.monkey.retromusic.EXTRA_SONG 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.db.SongEntity import code.name.monkey.retromusic.db.SongEntity
import code.name.monkey.retromusic.db.toSongsEntity
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.LibraryViewModel
import code.name.monkey.retromusic.fragments.ReloadType.Playlists import code.name.monkey.retromusic.fragments.ReloadType.Playlists
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.androidx.viewmodel.ext.android.sharedViewModel import org.koin.androidx.viewmodel.ext.android.sharedViewModel
class AddToPlaylistDialog : BottomSheetDialogFragment() { class AddToPlaylistDialog : DialogFragment() {
private val libraryViewModel by sharedViewModel<LibraryViewModel>() private val libraryViewModel by sharedViewModel<LibraryViewModel>()
companion object { companion object {
fun create(playlistEntities: List<PlaylistEntity>, song: Song): AddToPlaylistDialog { fun create(playlistEntities: List<PlaylistEntity>, song: Song): AddToPlaylistDialog {
val list = mutableListOf<Song>() val list: MutableList<Song> = mutableListOf()
list.add(song) list.add(song)
return create(playlistEntities, list) return create(playlistEntities, list)
} }
@ -41,12 +42,13 @@ class AddToPlaylistDialog : BottomSheetDialogFragment() {
} }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val playlistEntities = extraNotNull<List<PlaylistEntity>>(EXTRA_PLAYLISTS).value val playlistEntities: List<PlaylistEntity> =
val songs = extraNotNull<List<Song>>(EXTRA_SONG).value extraNotNull<List<PlaylistEntity>>(EXTRA_PLAYLISTS).value
val playlistNames = mutableListOf<String>() val songs: List<Song> = extraNotNull<List<Song>>(EXTRA_SONG).value
val playlistNames: MutableList<String> = mutableListOf()
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 (entity: PlaylistEntity in playlistEntities) {
playlistNames.add(p.playlistName) playlistNames.add(entity.playlistName)
} }
return materialDialog(R.string.add_playlist_title) return materialDialog(R.string.add_playlist_title)
.setItems(playlistNames.toTypedArray()) { _, which -> .setItems(playlistNames.toTypedArray()) { _, which ->
@ -55,7 +57,8 @@ class AddToPlaylistDialog : BottomSheetDialogFragment() {
.show(requireActivity().supportFragmentManager, "Dialog") .show(requireActivity().supportFragmentManager, "Dialog")
} else { } else {
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
val songEntities = songs.toSongEntity(playlistEntities[which - 1]) val songEntities: List<SongEntity> =
songs.toSongsEntity(playlistEntities[which - 1])
libraryViewModel.insertSongs(songEntities) libraryViewModel.insertSongs(songEntities)
libraryViewModel.forceReload(Playlists) libraryViewModel.forceReload(Playlists)
} }
@ -65,9 +68,3 @@ class AddToPlaylistDialog : BottomSheetDialogFragment() {
.create().colorButtons() .create().colorButtons()
} }
} }
private fun List<Song>.toSongEntity(playlistEntity: PlaylistEntity): List<SongEntity> {
return map {
it.toSongEntity(playlistEntity.playListId)
}
}

View file

@ -1,4 +1,55 @@
package code.name.monkey.retromusic.dialogs package code.name.monkey.retromusic.dialogs
class SavePlaylistDialog { import android.app.Dialog
import android.os.Bundle
import android.widget.Toast
import androidx.core.os.bundleOf
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.EXTRA_PLAYLIST
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.db.PlaylistWithSongs
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.util.PlaylistsUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class SavePlaylistDialog : DialogFragment() {
companion object {
fun create(playlistWithSongs: PlaylistWithSongs): SavePlaylistDialog {
return SavePlaylistDialog().apply {
arguments = bundleOf(
EXTRA_PLAYLIST to playlistWithSongs
)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch(Dispatchers.IO) {
val playlistWithSongs: PlaylistWithSongs =
extraNotNull<PlaylistWithSongs>(EXTRA_PLAYLIST).value
val file = PlaylistsUtil.savePlaylistWithSongs(requireContext(), playlistWithSongs)
withContext(Dispatchers.Main) {
Toast.makeText(
requireContext(),
String.format(App.getContext().getString(R.string.saved_playlist_to), file),
Toast.LENGTH_LONG
).show()
dismiss()
}
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return materialDialog(R.string.save_playlist_title)
.setView(R.layout.loading)
.create().colorButtons()
}
} }

View file

@ -13,7 +13,10 @@
*/ */
package code.name.monkey.retromusic.helper package code.name.monkey.retromusic.helper
import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.db.toSongs
import code.name.monkey.retromusic.model.Playlist import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.model.Song
import java.io.BufferedWriter import java.io.BufferedWriter
import java.io.File import java.io.File
import java.io.FileWriter import java.io.FileWriter
@ -42,4 +45,25 @@ object M3UWriter : M3UConstants {
} }
return file return file
} }
@JvmStatic
@Throws(IOException::class)
fun writeIO(dir: File, playlistWithSongs: PlaylistWithSongs): File {
if (!dir.exists()) dir.mkdirs()
val fileName = "${playlistWithSongs.playlistEntity.playlistName}.${M3UConstants.EXTENSION}"
val file = File(dir, fileName)
val songs: List<Song> = playlistWithSongs.songs.toSongs()
if (songs.isNotEmpty()) {
val bufferedWriter = BufferedWriter(FileWriter(file))
bufferedWriter.write(M3UConstants.HEADER)
songs.forEach {
bufferedWriter.newLine()
bufferedWriter.write(M3UConstants.ENTRY + it.duration + M3UConstants.DURATION_SEPARATOR + it.artistName + " - " + it.title)
bufferedWriter.newLine()
bufferedWriter.write(it.data)
}
bufferedWriter.close()
}
return file
}
} }

View file

@ -15,24 +15,17 @@
package code.name.monkey.retromusic.helper.menu package code.name.monkey.retromusic.helper.menu
import android.content.Context
import android.view.MenuItem import android.view.MenuItem
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.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.db.PlaylistWithSongs import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.db.toSongs import code.name.monkey.retromusic.db.toSongs
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
import code.name.monkey.retromusic.dialogs.DeletePlaylistDialog import code.name.monkey.retromusic.dialogs.DeletePlaylistDialog
import code.name.monkey.retromusic.dialogs.RenamePlaylistDialog import code.name.monkey.retromusic.dialogs.RenamePlaylistDialog
import code.name.monkey.retromusic.dialogs.SavePlaylistDialog
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.model.AbsCustomPlaylist
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.repository.RealRepository import code.name.monkey.retromusic.repository.RealRepository
import code.name.monkey.retromusic.util.PlaylistsUtil
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -81,42 +74,11 @@ object PlaylistMenuHelper : KoinComponent {
return true return true
} }
R.id.action_save_playlist -> { R.id.action_save_playlist -> {
//SavePlaylistAsyncTask(activity).execute(playlistWithSongs.songs.toSongs()) SavePlaylistDialog.create(playlistWithSongs)
Toast.makeText(activity, "Coming soon", Toast.LENGTH_SHORT).show() .show(activity.supportFragmentManager, "SavePlaylist")
return true return true
} }
} }
return false return false
} }
private fun getPlaylistSongs(
playlist: Playlist
): List<Song> {
return if (playlist is AbsCustomPlaylist) {
playlist.songs()
} else {
playlist.getSongs()
}
}
private class SavePlaylistAsyncTask(context: Context) :
WeakContextAsyncTask<Playlist, String, String>(context) {
override fun doInBackground(vararg params: Playlist): String {
return String.format(
App.getContext().getString(
R.string
.saved_playlist_to
), PlaylistsUtil.savePlaylist(App.getContext(), params[0])
)
}
override fun onPostExecute(string: String) {
super.onPostExecute(string)
val context = context
if (context != null) {
Toast.makeText(context, string, Toast.LENGTH_LONG).show()
}
}
}
} }

View file

@ -33,6 +33,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.db.PlaylistWithSongs;
import code.name.monkey.retromusic.helper.M3UWriter; import code.name.monkey.retromusic.helper.M3UWriter;
import code.name.monkey.retromusic.model.Playlist; import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.model.PlaylistSong; import code.name.monkey.retromusic.model.PlaylistSong;
@ -250,6 +251,10 @@ public class PlaylistsUtil {
return M3UWriter.write(new File(Environment.getExternalStorageDirectory(), "Playlists"), playlist); return M3UWriter.write(new File(Environment.getExternalStorageDirectory(), "Playlists"), playlist);
} }
public static File savePlaylistWithSongs(Context context, PlaylistWithSongs playlist) throws IOException {
return M3UWriter.writeIO(new File(Environment.getExternalStorageDirectory(), "Playlists"), playlist);
}
public static boolean doesPlaylistExist(@NonNull final Context context, final int playlistId) { public static boolean doesPlaylistExist(@NonNull final Context context, final int playlistId) {
return playlistId != -1 && doesPlaylistExist(context, return playlistId != -1 && doesPlaylistExist(context,
MediaStore.Audio.Playlists._ID + "=?", MediaStore.Audio.Playlists._ID + "=?",

View file

@ -20,7 +20,7 @@
android:padding="14dp"> android:padding="14dp">
<ProgressBar <ProgressBar
style="@style/Widget.AppCompat.ProgressBar.Horizontal" style="@style/Widget.MaterialComponents.ProgressIndicator.Linear.Indeterminate"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:indeterminate="true" /> android:indeterminate="true" />