Add save playlist 💾
This commit is contained in:
parent
41e8aa8a03
commit
6e8ff6ab71
7 changed files with 105 additions and 60 deletions
|
@ -86,4 +86,10 @@ fun Song.toPlayCount(): PlayCountEntity {
|
||||||
System.currentTimeMillis(),
|
System.currentTimeMillis(),
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun List<Song>.toSongsEntity(playlistEntity: PlaylistEntity): List<SongEntity> {
|
||||||
|
return map {
|
||||||
|
it.toSongEntity(playlistEntity.playListId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -64,10 +67,4 @@ class AddToPlaylistDialog : BottomSheetDialogFragment() {
|
||||||
}
|
}
|
||||||
.create().colorButtons()
|
.create().colorButtons()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<Song>.toSongEntity(playlistEntity: PlaylistEntity): List<SongEntity> {
|
|
||||||
return map {
|
|
||||||
it.toSongEntity(playlistEntity.playListId)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 + "=?",
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
Loading…
Reference in a new issue