Conflicts:
	README.md
	app/build.gradle
	app/release/output-metadata.json
	app/src/main/java/code/name/monkey/retromusic/Result.kt
	app/src/main/java/code/name/monkey/retromusic/activities/PurchaseActivity.kt
	app/src/main/java/code/name/monkey/retromusic/activities/SupportDevelopmentActivity.kt
	app/src/main/java/code/name/monkey/retromusic/deezer/DeezerApiService.kt
	app/src/main/java/code/name/monkey/retromusic/deezer/DeezerResponse.kt
	app/src/main/java/io/github/muntashirakon/music/MainModule.kt
	app/src/main/java/io/github/muntashirakon/music/Result.kt
	app/src/main/java/io/github/muntashirakon/music/activities/MainActivity.kt
	app/src/main/java/io/github/muntashirakon/music/activities/base/AbsMusicServiceActivity.kt
	app/src/main/java/io/github/muntashirakon/music/activities/base/AbsSlidingMusicPanelActivity.kt
	app/src/main/java/io/github/muntashirakon/music/activities/tageditor/AlbumTagEditorActivity.kt
	app/src/main/java/io/github/muntashirakon/music/adapter/album/HorizontalAlbumAdapter.kt
	app/src/main/java/io/github/muntashirakon/music/adapter/playlist/PlaylistAdapter.kt
	app/src/main/java/io/github/muntashirakon/music/adapter/song/OrderablePlaylistSongAdapter.kt
	app/src/main/java/io/github/muntashirakon/music/adapter/song/PlayingQueueAdapter.kt
	app/src/main/java/io/github/muntashirakon/music/deezer/DeezerApiService.kt
	app/src/main/java/io/github/muntashirakon/music/deezer/DeezerResponse.kt
	app/src/main/java/io/github/muntashirakon/music/dialogs/AddToPlaylistDialog.kt
	app/src/main/java/io/github/muntashirakon/music/dialogs/CreatePlaylistDialog.kt
	app/src/main/java/io/github/muntashirakon/music/dialogs/DeletePlaylistDialog.kt
	app/src/main/java/io/github/muntashirakon/music/dialogs/DeleteSongsAsyncTask.java
	app/src/main/java/io/github/muntashirakon/music/dialogs/DeleteSongsDialog.kt
	app/src/main/java/io/github/muntashirakon/music/dialogs/RemoveFromPlaylistDialog.kt
	app/src/main/java/io/github/muntashirakon/music/dialogs/RenamePlaylistDialog.kt
	app/src/main/java/io/github/muntashirakon/music/dialogs/RetroSingleCheckedListAdapter.kt
	app/src/main/java/io/github/muntashirakon/music/extensions/ActivityEx.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/DetailListFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/LibraryViewModel.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/MiniPlayerFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/albums/AlbumDetailsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/albums/AlbumDetailsViewModel.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/albums/AlbumsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/artists/ArtistDetailsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/artists/ArtistDetailsViewModel.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/artists/ArtistsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/base/AbsPlayerFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/genres/GenresFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/home/HomeFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/library/LibraryFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/player/classic/ClassicPlayerFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/player/fit/FitPlaybackControlsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/player/gradient/GradientPlayerFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/playlists/PlaylistDetailsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/playlists/PlaylistDetailsViewModel.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/playlists/PlaylistsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/queue/PlayingQueueFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/settings/MainSettingsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/settings/OtherSettingsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/songs/SongsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/glide/artistimage/ArtistImageLoader.kt
	app/src/main/java/io/github/muntashirakon/music/helper/M3UWriter.kt
	app/src/main/java/io/github/muntashirakon/music/helper/menu/GenreMenuHelper.kt
	app/src/main/java/io/github/muntashirakon/music/helper/menu/PlaylistMenuHelper.kt
	app/src/main/java/io/github/muntashirakon/music/helper/menu/SongMenuHelper.kt
	app/src/main/java/io/github/muntashirakon/music/helper/menu/SongsMenuHelper.kt
	app/src/main/java/io/github/muntashirakon/music/model/CategoryInfo.java
	app/src/main/java/io/github/muntashirakon/music/model/DeezerResponse.kt
	app/src/main/java/io/github/muntashirakon/music/model/Home.kt
	app/src/main/java/io/github/muntashirakon/music/model/PlaylistSong.java
	app/src/main/java/io/github/muntashirakon/music/network/DeezerService.kt
	app/src/main/java/io/github/muntashirakon/music/network/Result.kt
	app/src/main/java/io/github/muntashirakon/music/network/RetrofitClient.kt
	app/src/main/java/io/github/muntashirakon/music/repository/GenreRepository.kt
	app/src/main/java/io/github/muntashirakon/music/repository/PlaylistRepository.kt
	app/src/main/java/io/github/muntashirakon/music/repository/PlaylistSongsLoader.kt
	app/src/main/java/io/github/muntashirakon/music/repository/Repository.kt
	app/src/main/java/io/github/muntashirakon/music/repository/SongRepository.kt
	app/src/main/java/io/github/muntashirakon/music/service/MusicService.java
	app/src/main/java/io/github/muntashirakon/music/util/AppRater.kt
	app/src/main/java/io/github/muntashirakon/music/util/MusicUtil.kt
	app/src/main/java/io/github/muntashirakon/music/util/PlaylistsUtil.java
	app/src/main/res/font/pacifico.xml
	app/src/main/res/layout/fragment_gradient_player.xml
	app/src/main/res/layout/fragment_library.xml
	app/src/main/res/layout/fragment_main.xml
	app/src/main/res/layout/fragment_main_settings.xml
	app/src/main/res/navigation/library_graph.xml
	app/src/main/res/navigation/main_graph.xml
This commit is contained in:
Muntashir Al-Islam 2020-09-22 11:14:00 +06:00
commit 6df00b3e3a
244 changed files with 4912 additions and 2578 deletions

View file

@ -21,7 +21,7 @@ import io.github.muntashirakon.music.R
object HorizontalAdapterHelper {
const val LAYOUT_RES = R.layout.item_image
const val LAYOUT_RES = R.layout.item_album_card
private const val TYPE_FIRST = 1
private const val TYPE_MIDDLE = 2

View file

@ -13,8 +13,10 @@
*/
package io.github.muntashirakon.music.helper
import android.content.Context
import io.github.muntashirakon.music.db.PlaylistWithSongs
import io.github.muntashirakon.music.db.toSongs
import io.github.muntashirakon.music.model.Playlist
import io.github.muntashirakon.music.model.Song
import java.io.BufferedWriter
import java.io.File
import java.io.FileWriter
@ -24,14 +26,13 @@ object M3UWriter : M3UConstants {
@JvmStatic
@Throws(IOException::class)
fun write(
context: Context,
dir: File,
playlist: Playlist
): File? {
if (!dir.exists()) dir.mkdirs()
val file = File(dir, playlist.name + "." + M3UConstants.EXTENSION)
val songs = playlist.getSongs()
if (songs.size > 0) {
if (songs.isNotEmpty()) {
val bw = BufferedWriter(FileWriter(file))
bw.write(M3UConstants.HEADER)
for (song in songs) {
@ -44,4 +45,25 @@ object M3UWriter : M3UConstants {
}
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,7 +15,6 @@
package io.github.muntashirakon.music.helper
import android.app.SearchManager
import android.content.Context
import android.os.Bundle
import android.provider.MediaStore
import io.github.muntashirakon.music.model.Song
@ -33,7 +32,7 @@ object SearchQueryHelper : KoinComponent {
var songs = ArrayList<Song>()
@JvmStatic
fun getSongs(context: Context, extras: Bundle): List<Song> {
fun getSongs(extras: Bundle): List<Song> {
val query = extras.getString(SearchManager.QUERY, null)
val artistName = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST, null)
val albumName = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM, null)
@ -45,9 +44,9 @@ object SearchQueryHelper : KoinComponent {
songRepository.makeSongCursor(
ARTIST_SELECTION + AND + ALBUM_SELECTION + AND + TITLE_SELECTION,
arrayOf(
artistName.toLowerCase(),
albumName.toLowerCase(),
titleName.toLowerCase()
artistName.toLowerCase(Locale.getDefault()),
albumName.toLowerCase(Locale.getDefault()),
titleName.toLowerCase(Locale.getDefault())
)
)
)
@ -59,7 +58,10 @@ object SearchQueryHelper : KoinComponent {
songs = songRepository.songs(
songRepository.makeSongCursor(
ARTIST_SELECTION + AND + TITLE_SELECTION,
arrayOf(artistName.toLowerCase(), titleName.toLowerCase())
arrayOf(
artistName.toLowerCase(Locale.getDefault()),
titleName.toLowerCase(Locale.getDefault())
)
)
)
}
@ -70,7 +72,10 @@ object SearchQueryHelper : KoinComponent {
songs = songRepository.songs(
songRepository.makeSongCursor(
ALBUM_SELECTION + AND + TITLE_SELECTION,
arrayOf(albumName.toLowerCase(), titleName.toLowerCase())
arrayOf(
albumName.toLowerCase(Locale.getDefault()),
titleName.toLowerCase(Locale.getDefault())
)
)
)
}
@ -81,7 +86,7 @@ object SearchQueryHelper : KoinComponent {
songs = songRepository.songs(
songRepository.makeSongCursor(
ARTIST_SELECTION,
arrayOf(artistName.toLowerCase())
arrayOf(artistName.toLowerCase(Locale.getDefault()))
)
)
}
@ -92,7 +97,7 @@ object SearchQueryHelper : KoinComponent {
songs = songRepository.songs(
songRepository.makeSongCursor(
ALBUM_SELECTION,
arrayOf(albumName.toLowerCase())
arrayOf(albumName.toLowerCase(Locale.getDefault()))
)
)
}
@ -103,7 +108,7 @@ object SearchQueryHelper : KoinComponent {
songs = songRepository.songs(
songRepository.makeSongCursor(
TITLE_SELECTION,
arrayOf(titleName.toLowerCase())
arrayOf(titleName.toLowerCase(Locale.getDefault()))
)
)
}
@ -113,7 +118,7 @@ object SearchQueryHelper : KoinComponent {
songs = songRepository.songs(
songRepository.makeSongCursor(
ARTIST_SELECTION,
arrayOf(query.toLowerCase())
arrayOf(query.toLowerCase(Locale.getDefault()))
)
)
@ -123,7 +128,7 @@ object SearchQueryHelper : KoinComponent {
songs = songRepository.songs(
songRepository.makeSongCursor(
ALBUM_SELECTION,
arrayOf(query.toLowerCase())
arrayOf(query.toLowerCase(Locale.getDefault()))
)
)
if (songs.isNotEmpty()) {
@ -132,7 +137,7 @@ object SearchQueryHelper : KoinComponent {
songs = songRepository.songs(
songRepository.makeSongCursor(
TITLE_SELECTION,
arrayOf(query.toLowerCase())
arrayOf(query.toLowerCase(Locale.getDefault()))
)
)
return if (songs.isNotEmpty()) {

View file

@ -22,7 +22,13 @@ import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.model.Genre
import io.github.muntashirakon.music.model.Song
import io.github.muntashirakon.music.repository.GenreRepository
import io.github.muntashirakon.music.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
import org.koin.core.inject
object GenreMenuHelper : KoinComponent {
@ -38,8 +44,13 @@ object GenreMenuHelper : KoinComponent {
return true
}
R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(getGenreSongs(genre))
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
CoroutineScope(Dispatchers.IO).launch {
val playlists = get<RealRepository>().fetchPlaylists()
withContext(Dispatchers.Main) {
AddToPlaylistDialog.create(playlists, getGenreSongs(genre))
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
}
}
return true
}
R.id.action_add_to_current_playing -> {

View file

@ -15,95 +15,70 @@
package io.github.muntashirakon.music.helper.menu
import android.app.Activity
import android.content.Context
import android.view.MenuItem
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import io.github.muntashirakon.music.App
import io.github.muntashirakon.music.R
import io.github.muntashirakon.music.db.PlaylistWithSongs
import io.github.muntashirakon.music.db.toSongs
import io.github.muntashirakon.music.dialogs.AddToPlaylistDialog
import io.github.muntashirakon.music.dialogs.DeletePlaylistDialog
import io.github.muntashirakon.music.dialogs.RenamePlaylistDialog
import io.github.muntashirakon.music.dialogs.SavePlaylistDialog
import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.misc.WeakContextAsyncTask
import io.github.muntashirakon.music.model.AbsCustomPlaylist
import io.github.muntashirakon.music.model.Playlist
import io.github.muntashirakon.music.model.Song
import io.github.muntashirakon.music.util.PlaylistsUtil
import io.github.muntashirakon.music.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 PlaylistMenuHelper {
object PlaylistMenuHelper : KoinComponent {
fun handleMenuClick(
activity: FragmentActivity,
playlist: Playlist, item: MenuItem
playlistWithSongs: PlaylistWithSongs, item: MenuItem
): Boolean {
when (item.itemId) {
R.id.action_play -> {
MusicPlayerRemote.openQueue(getPlaylistSongs(activity, playlist), 9, true)
MusicPlayerRemote.openQueue(playlistWithSongs.songs.toSongs(), 0, true)
return true
}
R.id.action_play_next -> {
MusicPlayerRemote.playNext(getPlaylistSongs(activity, playlist))
MusicPlayerRemote.playNext(playlistWithSongs.songs.toSongs())
return true
}
R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(getPlaylistSongs(activity, playlist))
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
CoroutineScope(Dispatchers.IO).launch {
val playlists = get<RealRepository>().fetchPlaylists()
withContext(Dispatchers.Main) {
AddToPlaylistDialog.create(playlists, playlistWithSongs.songs.toSongs())
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
}
}
return true
}
R.id.action_add_to_current_playing -> {
MusicPlayerRemote.enqueue(getPlaylistSongs(activity, playlist))
MusicPlayerRemote.enqueue(playlistWithSongs.songs.toSongs())
return true
}
R.id.action_rename_playlist -> {
RenamePlaylistDialog.create(playlist.id.toLong())
RenamePlaylistDialog.create(playlistWithSongs.playlistEntity)
.show(activity.supportFragmentManager, "RENAME_PLAYLIST")
return true
}
R.id.action_delete_playlist -> {
DeletePlaylistDialog.create(playlist)
DeletePlaylistDialog.create(playlistWithSongs.playlistEntity)
.show(activity.supportFragmentManager, "DELETE_PLAYLIST")
return true
}
R.id.action_save_playlist -> {
SavePlaylistAsyncTask(activity).execute(playlist)
SavePlaylistDialog.create(playlistWithSongs)
.show(activity.supportFragmentManager, "SavePlaylist")
return true
}
}
return false
}
private fun getPlaylistSongs(
activity: Activity,
playlist: Playlist
): List<Song> {
return if (playlist is AbsCustomPlaylist) {
playlist.songs()
} else {
playlist.getSongs()
}
}
private class SavePlaylistAsyncTask internal constructor(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

@ -32,10 +32,17 @@ import io.github.muntashirakon.music.dialogs.SongDetailDialog
import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.interfaces.PaletteColorHolder
import io.github.muntashirakon.music.model.Song
import io.github.muntashirakon.music.repository.RealRepository
import io.github.muntashirakon.music.util.MusicUtil
import io.github.muntashirakon.music.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
fun handleMenuClick(activity: FragmentActivity, song: Song, menuItemId: Int): Boolean {
@ -63,8 +70,13 @@ object SongMenuHelper {
return true
}
R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(song)
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
CoroutineScope(Dispatchers.IO).launch {
val playlists = get<RealRepository>().fetchPlaylists()
withContext(Dispatchers.Main) {
AddToPlaylistDialog.create(playlists, song)
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
}
}
return true
}
R.id.action_play_next -> {

View file

@ -20,9 +20,15 @@ import io.github.muntashirakon.music.dialogs.AddToPlaylistDialog
import io.github.muntashirakon.music.dialogs.DeleteSongsDialog
import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.model.Song
import io.github.muntashirakon.music.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 {
object SongsMenuHelper : KoinComponent {
fun handleMenuClick(
activity: FragmentActivity,
songs: List<Song>,
@ -38,8 +44,13 @@ object SongsMenuHelper {
return true
}
R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(songs)
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
CoroutineScope(Dispatchers.IO).launch {
val playlists = get<RealRepository>().fetchPlaylists()
withContext(Dispatchers.Main) {
AddToPlaylistDialog.create(playlists, songs)
.show(activity.supportFragmentManager, "ADD_PLAYLIST")
}
}
return true
}
R.id.action_delete_from_device -> {