Code refactor
parent
c379342f6a
commit
6881e9a4c1
|
@ -68,7 +68,7 @@ favorite songs. No other music player has this feature.
|
||||||
|
|
||||||
We are trying our best to bring you the best user experience. The app is regulary being updated for bug fixes and new features.
|
We are trying our best to bring you the best user experience. The app is regulary being updated for bug fixes and new features.
|
||||||
|
|
||||||
### FAQ
|
### ❓ FAQ
|
||||||
Please read the FAQ here: https://del.dog/RetroFaq
|
Please read the FAQ here: https://del.dog/RetroFaq
|
||||||
|
|
||||||
In any case, you find or notice any bugs please report them by
|
In any case, you find or notice any bugs please report them by
|
||||||
|
|
|
@ -3,8 +3,8 @@ package code.name.monkey.retromusic
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
import code.name.monkey.retromusic.db.BlackListStoreDao
|
||||||
import code.name.monkey.retromusic.db.BlackListStoreEntity
|
import code.name.monkey.retromusic.db.BlackListStoreEntity
|
||||||
import code.name.monkey.retromusic.db.PlaylistDao
|
|
||||||
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
||||||
import code.name.monkey.retromusic.db.RetroDatabase
|
import code.name.monkey.retromusic.db.RetroDatabase
|
||||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||||
|
@ -13,6 +13,7 @@ import code.name.monkey.retromusic.fragments.artists.ArtistDetailsViewModel
|
||||||
import code.name.monkey.retromusic.fragments.genres.GenreDetailsViewModel
|
import code.name.monkey.retromusic.fragments.genres.GenreDetailsViewModel
|
||||||
import code.name.monkey.retromusic.fragments.playlists.PlaylistDetailsViewModel
|
import code.name.monkey.retromusic.fragments.playlists.PlaylistDetailsViewModel
|
||||||
import code.name.monkey.retromusic.fragments.search.SearchViewModel
|
import code.name.monkey.retromusic.fragments.search.SearchViewModel
|
||||||
|
import code.name.monkey.retromusic.fragments.songs.SongsViewModel
|
||||||
import code.name.monkey.retromusic.model.Genre
|
import code.name.monkey.retromusic.model.Genre
|
||||||
import code.name.monkey.retromusic.network.networkModule
|
import code.name.monkey.retromusic.network.networkModule
|
||||||
import code.name.monkey.retromusic.repository.*
|
import code.name.monkey.retromusic.repository.*
|
||||||
|
@ -35,7 +36,7 @@ private val roomModule = module {
|
||||||
super.onOpen(db)
|
super.onOpen(db)
|
||||||
GlobalScope.launch(IO) {
|
GlobalScope.launch(IO) {
|
||||||
FilePathUtil.blacklistFilePaths().map {
|
FilePathUtil.blacklistFilePaths().map {
|
||||||
get<PlaylistDao>().insertBlacklistPath(BlackListStoreEntity(it))
|
get<BlackListStoreDao>().insertBlacklistPath(BlackListStoreEntity(it))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,9 +49,17 @@ private val roomModule = module {
|
||||||
get<RetroDatabase>().playlistDao()
|
get<RetroDatabase>().playlistDao()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
factory {
|
||||||
|
get<RetroDatabase>().blackListStore()
|
||||||
|
}
|
||||||
|
|
||||||
|
factory {
|
||||||
|
get<RetroDatabase>().playCountDao()
|
||||||
|
}
|
||||||
|
|
||||||
single {
|
single {
|
||||||
RealRoomRepository(get())
|
RealRoomRepository(get(), get(), get())
|
||||||
} bind RoomPlaylistRepository::class
|
} bind RoomRepository::class
|
||||||
}
|
}
|
||||||
private val mainModule = module {
|
private val mainModule = module {
|
||||||
single {
|
single {
|
||||||
|
@ -143,6 +152,10 @@ private val viewModules = module {
|
||||||
viewModel {
|
viewModel {
|
||||||
SearchViewModel(get())
|
SearchViewModel(get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel {
|
||||||
|
SongsViewModel(get())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val appModules = listOf(mainModule, dataModule, viewModules, networkModule, roomModule)
|
val appModules = listOf(mainModule, dataModule, viewModules, networkModule, roomModule)
|
|
@ -34,7 +34,6 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
|
||||||
}
|
}
|
||||||
|
|
||||||
private val repository by inject<Repository>()
|
private val repository by inject<Repository>()
|
||||||
|
|
||||||
private var blockRequestPermissions = false
|
private var blockRequestPermissions = false
|
||||||
|
|
||||||
override fun createContentView(): View {
|
override fun createContentView(): View {
|
||||||
|
@ -133,7 +132,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
|
||||||
if (id >= 0) {
|
if (id >= 0) {
|
||||||
lifecycleScope.launch(Dispatchers.Main) {
|
lifecycleScope.launch(Dispatchers.Main) {
|
||||||
val position = intent.getIntExtra("position", 0)
|
val position = intent.getIntExtra("position", 0)
|
||||||
openQueue(repository.albumById(id).songs!!, position, true)
|
openQueue(repository.albumByIdAsync(id).songs!!, position, true)
|
||||||
handled = true
|
handled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,23 @@ import android.Manifest
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
|
import code.name.monkey.retromusic.db.toPlayCount
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||||
|
import code.name.monkey.retromusic.repository.RealRepository
|
||||||
import code.name.monkey.retromusic.service.MusicService.*
|
import code.name.monkey.retromusic.service.MusicService.*
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.koin.android.ext.android.inject
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventListener {
|
abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventListener {
|
||||||
|
|
||||||
private val mMusicServiceEventListeners = ArrayList<MusicServiceEventListener>()
|
private val mMusicServiceEventListeners = ArrayList<MusicServiceEventListener>()
|
||||||
|
private val repository: RealRepository by inject()
|
||||||
private var serviceToken: MusicPlayerRemote.ServiceToken? = null
|
private var serviceToken: MusicPlayerRemote.ServiceToken? = null
|
||||||
private var musicStateReceiver: MusicStateReceiver? = null
|
private var musicStateReceiver: MusicStateReceiver? = null
|
||||||
private var receiverRegistered: Boolean = false
|
private var receiverRegistered: Boolean = false
|
||||||
|
@ -93,6 +99,22 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventLis
|
||||||
for (listener in mMusicServiceEventListeners) {
|
for (listener in mMusicServiceEventListeners) {
|
||||||
listener.onPlayingMetaChanged()
|
listener.onPlayingMetaChanged()
|
||||||
}
|
}
|
||||||
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val entity = repository.songPresentInHistory(MusicPlayerRemote.currentSong)
|
||||||
|
if (entity != null) {
|
||||||
|
repository.updateHistorySong(MusicPlayerRemote.currentSong)
|
||||||
|
} else {
|
||||||
|
repository.addSongToHistory(MusicPlayerRemote.currentSong)
|
||||||
|
}
|
||||||
|
val songs = repository.checkSongExistInPlayCount(MusicPlayerRemote.currentSong.id)
|
||||||
|
if (songs.isNotEmpty()) {
|
||||||
|
repository.updateSongInPlayCount(songs.first().apply {
|
||||||
|
playCount += 1
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
repository.insertSongInPlayCount(MusicPlayerRemote.currentSong.toPlayCount())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onQueueChanged() {
|
override fun onQueueChanged() {
|
||||||
|
|
|
@ -73,7 +73,6 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
setContentView(createContentView())
|
setContentView(createContentView())
|
||||||
chooseFragmentForTheme()
|
chooseFragmentForTheme()
|
||||||
setupSlidingUpPanel()
|
setupSlidingUpPanel()
|
||||||
addMusicServiceEventListener(libraryViewModel)
|
|
||||||
|
|
||||||
setupBottomSheet()
|
setupBottomSheet()
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.OvershootInterpolator
|
import android.view.animation.OvershootInterpolator
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
|
@ -182,11 +181,9 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
|
||||||
saveFab = findViewById(R.id.saveTags)
|
saveFab = findViewById(R.id.saveTags)
|
||||||
getIntentExtras()
|
getIntentExtras()
|
||||||
|
|
||||||
lifecycleScope.launchWhenCreated {
|
songPaths = getSongPaths()
|
||||||
songPaths = getSongPaths()
|
if (songPaths!!.isEmpty()) {
|
||||||
if (songPaths!!.isEmpty()) {
|
finish()
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
setUpViews()
|
setUpViews()
|
||||||
}
|
}
|
||||||
|
@ -258,7 +255,7 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract suspend fun getSongPaths(): List<String>
|
protected abstract fun getSongPaths(): List<String>
|
||||||
|
|
||||||
protected fun searchWebFor(vararg keys: String) {
|
protected fun searchWebFor(vararg keys: String) {
|
||||||
val stringBuilder = StringBuilder()
|
val stringBuilder = StringBuilder()
|
||||||
|
|
|
@ -167,7 +167,7 @@ class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getSongPaths(): List<String> {
|
override fun getSongPaths(): List<String> {
|
||||||
val songs = repository.albumById(id).songs
|
val songs = repository.albumById(id).songs
|
||||||
val paths = ArrayList<String>(songs!!.size)
|
val paths = ArrayList<String>(songs!!.size)
|
||||||
for (song in songs) {
|
for (song in songs) {
|
||||||
|
|
|
@ -88,7 +88,7 @@ class SongTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
||||||
writeValuesToFiles(fieldKeyValueMap, null)
|
writeValuesToFiles(fieldKeyValueMap, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getSongPaths(): List<String> {
|
override fun getSongPaths(): List<String> {
|
||||||
val paths = ArrayList<String>(1)
|
val paths = ArrayList<String>(1)
|
||||||
paths.add(songRepository.song(id).data)
|
paths.add(songRepository.song(id).data)
|
||||||
return paths
|
return paths
|
||||||
|
|
|
@ -154,13 +154,11 @@ class PlaylistAdapter(
|
||||||
|
|
||||||
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
|
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
|
||||||
init {
|
init {
|
||||||
|
|
||||||
image?.apply {
|
image?.apply {
|
||||||
val iconPadding =
|
val iconPadding =
|
||||||
activity.resources.getDimensionPixelSize(R.dimen.list_item_image_icon_padding)
|
activity.resources.getDimensionPixelSize(R.dimen.list_item_image_icon_padding)
|
||||||
setPadding(iconPadding, iconPadding, iconPadding, iconPadding)
|
setPadding(iconPadding, iconPadding, iconPadding, iconPadding)
|
||||||
}
|
}
|
||||||
|
|
||||||
menu?.setOnClickListener { view ->
|
menu?.setOnClickListener { view ->
|
||||||
val popupMenu = PopupMenu(activity, view)
|
val popupMenu = PopupMenu(activity, view)
|
||||||
popupMenu.inflate(R.menu.menu_item_playlist)
|
popupMenu.inflate(R.menu.menu_item_playlist)
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package code.name.monkey.retromusic.db
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface BlackListStoreDao {
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
fun insertBlacklistPath(blackListStoreEntity: BlackListStoreEntity)
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insertBlacklistPath(blackListStoreEntities: List<BlackListStoreEntity>)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun deleteBlacklistPath(blackListStoreEntity: BlackListStoreEntity)
|
||||||
|
|
||||||
|
@Query("DELETE FROM BlackListStoreEntity")
|
||||||
|
suspend fun clearBlacklist()
|
||||||
|
|
||||||
|
@Query("SELECT * FROM BlackListStoreEntity")
|
||||||
|
fun blackListPaths(): List<BlackListStoreEntity>
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package code.name.monkey.retromusic.db
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface PlayCountDao {
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
fun insertSongInPlayCount(playCountEntity: PlayCountEntity)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
fun updateSongInPlayCount(playCountEntity: PlayCountEntity)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun deleteSongInPlayCount(playCountEntity: PlayCountEntity)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM PlayCountEntity WHERE id =:songId")
|
||||||
|
fun checkSongExistInPlayCount(songId: Int): List<PlayCountEntity>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM PlayCountEntity ORDER BY play_count DESC")
|
||||||
|
fun playCountSongs(): List<PlayCountEntity>
|
||||||
|
}
|
|
@ -63,30 +63,6 @@ interface PlaylistDao {
|
||||||
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id= :playlistId")
|
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id= :playlistId")
|
||||||
fun favoritesSongs(playlistId: Int): List<SongEntity>
|
fun favoritesSongs(playlistId: Int): List<SongEntity>
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
fun insertSongInPlayCount(playCountEntity: PlayCountEntity)
|
|
||||||
|
|
||||||
@Update
|
|
||||||
fun updateSongInPlayCount(playCountEntity: PlayCountEntity)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
fun deleteSongInPlayCount(playCountEntity: PlayCountEntity)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM PlayCountEntity WHERE id =:songId")
|
|
||||||
fun checkSongExistInPlayCount(songId: Int): List<PlayCountEntity>
|
|
||||||
|
|
||||||
@Query("SELECT * FROM PlayCountEntity ORDER BY play_count DESC")
|
|
||||||
fun playCountSongs(): List<PlayCountEntity>
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
fun insertBlacklistPath(blackListStoreEntity: BlackListStoreEntity)
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
suspend fun insertBlacklistPath(blackListStoreEntities: List<BlackListStoreEntity>)
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
suspend fun deleteBlacklistPath(blackListStoreEntity: BlackListStoreEntity)
|
|
||||||
|
|
||||||
@Query("DELETE FROM BlackListStoreEntity")
|
|
||||||
suspend fun clearBlacklist()
|
|
||||||
}
|
}
|
|
@ -5,9 +5,11 @@ import androidx.room.RoomDatabase
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
entities = [PlaylistEntity::class, SongEntity::class, HistoryEntity::class, PlayCountEntity::class, BlackListStoreEntity::class],
|
entities = [PlaylistEntity::class, SongEntity::class, HistoryEntity::class, PlayCountEntity::class, BlackListStoreEntity::class],
|
||||||
version = 18,
|
version = 19,
|
||||||
exportSchema = false
|
exportSchema = false
|
||||||
)
|
)
|
||||||
abstract class RetroDatabase : RoomDatabase() {
|
abstract class RetroDatabase : RoomDatabase() {
|
||||||
abstract fun playlistDao(): PlaylistDao
|
abstract fun playlistDao(): PlaylistDao
|
||||||
|
abstract fun blackListStore(): BlackListStoreDao
|
||||||
|
abstract fun playCountDao(): PlayCountDao
|
||||||
}
|
}
|
|
@ -54,7 +54,7 @@ class AddToRetroPlaylist : BottomSheetDialogFragment() {
|
||||||
return materialDialog(R.string.add_playlist_title)
|
return materialDialog(R.string.add_playlist_title)
|
||||||
.setItems(playlistNames.toTypedArray()) { _, which ->
|
.setItems(playlistNames.toTypedArray()) { _, which ->
|
||||||
if (which == 0) {
|
if (which == 0) {
|
||||||
CreateRetroPlaylist().show(requireActivity().supportFragmentManager, "Dialog")
|
CreateRetroPlaylist.create(songs).show(requireActivity().supportFragmentManager, "Dialog")
|
||||||
} else {
|
} else {
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
val songEntities = songs.toSongEntity(playlistEntities[which - 1])
|
val songEntities = songs.toSongEntity(playlistEntities[which - 1])
|
||||||
|
|
|
@ -5,14 +5,18 @@ 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 android.widget.Toast
|
||||||
|
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_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.extensions.colorButtons
|
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.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.repository.RealRepository
|
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
|
||||||
|
@ -25,8 +29,24 @@ import org.koin.androidx.viewmodel.ext.android.sharedViewModel
|
||||||
class CreateRetroPlaylist : DialogFragment() {
|
class CreateRetroPlaylist : DialogFragment() {
|
||||||
private val repository by inject<RealRepository>()
|
private val repository by inject<RealRepository>()
|
||||||
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
|
private val libraryViewModel by sharedViewModel<LibraryViewModel>()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun create(song: Song): CreateRetroPlaylist {
|
||||||
|
val list = mutableListOf<Song>()
|
||||||
|
list.add(song)
|
||||||
|
return create(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun create(songs: List<Song>): CreateRetroPlaylist {
|
||||||
|
return CreateRetroPlaylist().apply {
|
||||||
|
arguments = bundleOf(EXTRA_SONG to songs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
val songs = extraNotNull<List<Song>>(EXTRA_SONG).value
|
||||||
val playlistView: TextInputEditText = view.actionNewPlaylist
|
val playlistView: TextInputEditText = view.actionNewPlaylist
|
||||||
val playlistContainer: TextInputLayout = view.actionNewPlaylistContainer
|
val playlistContainer: TextInputLayout = view.actionNewPlaylistContainer
|
||||||
return materialDialog(R.string.new_playlist_title)
|
return materialDialog(R.string.new_playlist_title)
|
||||||
|
@ -38,13 +58,14 @@ class CreateRetroPlaylist : DialogFragment() {
|
||||||
if (!TextUtils.isEmpty(playlistName)) {
|
if (!TextUtils.isEmpty(playlistName)) {
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
if (repository.checkPlaylistExists(playlistName).isEmpty()) {
|
if (repository.checkPlaylistExists(playlistName).isEmpty()) {
|
||||||
repository.createPlaylist(PlaylistEntity(playlistName))
|
val playlistId = repository.createPlaylist(PlaylistEntity(playlistName))
|
||||||
|
println(playlistId)
|
||||||
|
repository.insertSongs(songs.map { it.toSongEntity(playlistId.toInt()) })
|
||||||
libraryViewModel.forceReload(Playlists)
|
libraryViewModel.forceReload(Playlists)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(requireContext(), "Playlist exists", Toast.LENGTH_SHORT)
|
Toast.makeText(requireContext(), "Playlist exists", Toast.LENGTH_SHORT)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
playlistContainer.error = "Playlist is can't be empty"
|
playlistContainer.error = "Playlist is can't be empty"
|
||||||
|
|
|
@ -35,7 +35,6 @@ import code.name.monkey.retromusic.R
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
|
||||||
fun Int.ripAlpha(): Int {
|
fun Int.ripAlpha(): Int {
|
||||||
|
@ -145,10 +144,6 @@ fun TextInputLayout.accentColor() {
|
||||||
isHintAnimationEnabled = true
|
isHintAnimationEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun TextInputEditText.accentColor() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun AppCompatImageView.accentColor(): Int {
|
fun AppCompatImageView.accentColor(): Int {
|
||||||
return ThemeStore.accentColor(context)
|
return ThemeStore.accentColor(context)
|
||||||
}
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package code.name.monkey.retromusic.fragments
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
open class CoroutineViewModel(
|
||||||
|
private val mainDispatcher: CoroutineDispatcher
|
||||||
|
) : ViewModel() {
|
||||||
|
private val job = Job()
|
||||||
|
protected val scope = CoroutineScope(job + mainDispatcher)
|
||||||
|
|
||||||
|
protected fun launch(
|
||||||
|
context: CoroutineContext = mainDispatcher,
|
||||||
|
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||||
|
block: suspend CoroutineScope.() -> Unit
|
||||||
|
) = scope.launch(context, start, block)
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
super.onCleared()
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
}
|
|
@ -85,7 +85,9 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
||||||
layoutManager = linearLayoutManager()
|
layoutManager = linearLayoutManager()
|
||||||
}
|
}
|
||||||
lifecycleScope.launch(IO) {
|
lifecycleScope.launch(IO) {
|
||||||
val songs = repository.recentSongs()
|
val songs = repository.playCountSongs().map {
|
||||||
|
it.toSong()
|
||||||
|
}
|
||||||
withContext(Main) { songAdapter.swapDataSet(songs) }
|
withContext(Main) { songAdapter.swapDataSet(songs) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,7 @@ import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
||||||
import code.name.monkey.retromusic.db.toPlayCount
|
|
||||||
import code.name.monkey.retromusic.fragments.ReloadType.*
|
import code.name.monkey.retromusic.fragments.ReloadType.*
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
|
||||||
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||||
import code.name.monkey.retromusic.model.*
|
import code.name.monkey.retromusic.model.*
|
||||||
import code.name.monkey.retromusic.repository.RealRepository
|
import code.name.monkey.retromusic.repository.RealRepository
|
||||||
|
@ -51,7 +49,7 @@ class LibraryViewModel(
|
||||||
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()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val loadHome: Deferred<List<Home>>
|
private val loadHome: Deferred<List<Home>>
|
||||||
|
@ -86,7 +84,6 @@ 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()
|
||||||
|
@ -121,22 +118,7 @@ class LibraryViewModel(
|
||||||
|
|
||||||
override fun onPlayingMetaChanged() {
|
override fun onPlayingMetaChanged() {
|
||||||
println("onPlayingMetaChanged")
|
println("onPlayingMetaChanged")
|
||||||
viewModelScope.launch(IO) {
|
|
||||||
val entity = repository.songPresentInHistory(MusicPlayerRemote.currentSong)
|
|
||||||
if (entity != null) {
|
|
||||||
repository.updateHistorySong(MusicPlayerRemote.currentSong)
|
|
||||||
} else {
|
|
||||||
repository.addSongToHistory(MusicPlayerRemote.currentSong)
|
|
||||||
}
|
|
||||||
val songs = repository.checkSongExistInPlayCount(MusicPlayerRemote.currentSong.id)
|
|
||||||
if (songs.isNotEmpty()) {
|
|
||||||
repository.updateSongInPlayCount(songs.first().apply {
|
|
||||||
playCount += playCount + 1
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
repository.insertSongInPlayCount(MusicPlayerRemote.currentSong.toPlayCount())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlayStateChanged() {
|
override fun onPlayStateChanged() {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import androidx.navigation.fragment.navArgs
|
||||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
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.EXTRA_ALBUM_ID
|
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
|
||||||
|
@ -32,6 +33,7 @@ import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
||||||
import code.name.monkey.retromusic.glide.AlbumGlideRequest
|
import code.name.monkey.retromusic.glide.AlbumGlideRequest
|
||||||
import code.name.monkey.retromusic.glide.ArtistGlideRequest
|
import code.name.monkey.retromusic.glide.ArtistGlideRequest
|
||||||
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
|
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
|
||||||
|
import code.name.monkey.retromusic.glide.SingleColorTarget
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.helper.SortOrder
|
import code.name.monkey.retromusic.helper.SortOrder
|
||||||
import code.name.monkey.retromusic.model.Album
|
import code.name.monkey.retromusic.model.Album
|
||||||
|
@ -77,9 +79,9 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
|
||||||
toolbar.title = null
|
toolbar.title = null
|
||||||
|
|
||||||
postponeEnterTransition()
|
postponeEnterTransition()
|
||||||
detailsViewModel.getAlbum().observe(viewLifecycleOwner, Observer {
|
detailsViewModel.getAlbum2().observe(viewLifecycleOwner, Observer {
|
||||||
showAlbum(it)
|
|
||||||
startPostponedEnterTransition()
|
startPostponedEnterTransition()
|
||||||
|
showAlbum(it)
|
||||||
})
|
})
|
||||||
detailsViewModel.getArtist().observe(viewLifecycleOwner, Observer {
|
detailsViewModel.getArtist().observe(viewLifecycleOwner, Observer {
|
||||||
loadArtistImage(it)
|
loadArtistImage(it)
|
||||||
|
@ -232,16 +234,18 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
|
||||||
.build()
|
.build()
|
||||||
.dontAnimate()
|
.dontAnimate()
|
||||||
.dontTransform()
|
.dontTransform()
|
||||||
.into(object : RetroMusicColoredTarget(image) {
|
.into(object : SingleColorTarget(image) {
|
||||||
override fun onColorReady(colors: MediaNotificationProcessor) {
|
override fun onColorReady(color: Int) {
|
||||||
setColors(colors)
|
setColors(color)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setColors(color: MediaNotificationProcessor) {
|
private fun setColors(color: Int) {
|
||||||
shuffleAction.applyColor(color.backgroundColor)
|
val finalColor =
|
||||||
playAction.applyOutlineColor(color.backgroundColor)
|
if (PreferenceUtil.isAdaptiveColor) color else ThemeStore.accentColor(requireContext())
|
||||||
|
shuffleAction.applyColor(finalColor)
|
||||||
|
playAction.applyOutlineColor(finalColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAlbumClick(albumId: Int, view: View) {
|
override fun onAlbumClick(albumId: Int, view: View) {
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
package code.name.monkey.retromusic.fragments.albums
|
package code.name.monkey.retromusic.fragments.albums
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.*
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||||
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.repository.RealRepository
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@ -24,7 +21,11 @@ class AlbumDetailsViewModel(
|
||||||
private val _lastFmAlbum = MutableLiveData<LastFmAlbum>()
|
private val _lastFmAlbum = MutableLiveData<LastFmAlbum>()
|
||||||
private val _moreAlbums = MutableLiveData<List<Album>>()
|
private val _moreAlbums = MutableLiveData<List<Album>>()
|
||||||
|
|
||||||
fun getAlbum(): LiveData<Album> = _album
|
fun getAlbum(): LiveData<Album> = liveData(IO) {
|
||||||
|
val album = realRepository.albumByIdAsync(albumId)
|
||||||
|
emit(album)
|
||||||
|
}
|
||||||
|
|
||||||
fun getArtist(): LiveData<Artist> = _artist
|
fun getArtist(): LiveData<Artist> = _artist
|
||||||
fun getAlbumInfo(): LiveData<LastFmAlbum> = _lastFmAlbum
|
fun getAlbumInfo(): LiveData<LastFmAlbum> = _lastFmAlbum
|
||||||
fun getMoreAlbums(): LiveData<List<Album>> = _moreAlbums
|
fun getMoreAlbums(): LiveData<List<Album>> = _moreAlbums
|
||||||
|
@ -33,17 +34,22 @@ class AlbumDetailsViewModel(
|
||||||
loadAlbumDetails()
|
loadAlbumDetails()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadAlbumDetails() = viewModelScope.launch {
|
fun getAlbum2() = liveData(context = viewModelScope.coroutineContext + IO) {
|
||||||
|
val album = realRepository.albumByIdAsync(albumId)
|
||||||
|
emit(album)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadAlbumDetails() = viewModelScope.launch(IO) {
|
||||||
val album = loadAlbumAsync.await() ?: throw NullPointerException("Album couldn't found")
|
val album = loadAlbumAsync.await() ?: throw NullPointerException("Album couldn't found")
|
||||||
_album.postValue(album)
|
_album.postValue(album)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadAlbumInfo(album: Album) = viewModelScope.launch(Dispatchers.IO) {
|
fun loadAlbumInfo(album: Album) = viewModelScope.launch(IO) {
|
||||||
val lastFmAlbum = realRepository.albumInfo(album.artistName ?: "-", album.title ?: "-")
|
val lastFmAlbum = realRepository.albumInfo(album.artistName ?: "-", album.title ?: "-")
|
||||||
_lastFmAlbum.postValue(lastFmAlbum)
|
_lastFmAlbum.postValue(lastFmAlbum)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadArtist(artistId: Int) = viewModelScope.launch(Dispatchers.IO) {
|
fun loadArtist(artistId: Int) = viewModelScope.launch(IO) {
|
||||||
val artist = realRepository.artistById(artistId)
|
val artist = realRepository.artistById(artistId)
|
||||||
_artist.postValue(artist)
|
_artist.postValue(artist)
|
||||||
|
|
||||||
|
@ -53,8 +59,8 @@ class AlbumDetailsViewModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
private val loadAlbumAsync: Deferred<Album?>
|
private val loadAlbumAsync: Deferred<Album?>
|
||||||
get() = viewModelScope.async(Dispatchers.IO) {
|
get() = viewModelScope.async(IO) {
|
||||||
realRepository.albumById(albumId)
|
realRepository.albumByIdAsync(albumId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMediaStoreChanged() {
|
override fun onMediaStoreChanged() {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import androidx.navigation.fragment.navArgs
|
||||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
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
|
||||||
|
@ -28,15 +29,15 @@ import code.name.monkey.retromusic.extensions.showToast
|
||||||
import code.name.monkey.retromusic.fragments.albums.AlbumClickListener
|
import code.name.monkey.retromusic.fragments.albums.AlbumClickListener
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
||||||
import code.name.monkey.retromusic.glide.ArtistGlideRequest
|
import code.name.monkey.retromusic.glide.ArtistGlideRequest
|
||||||
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
|
import code.name.monkey.retromusic.glide.SingleColorTarget
|
||||||
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.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.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
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.*
|
||||||
|
@ -181,19 +182,22 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d
|
||||||
private fun loadArtistImage(artist: Artist) {
|
private fun loadArtistImage(artist: Artist) {
|
||||||
ArtistGlideRequest.Builder.from(Glide.with(requireContext()), artist)
|
ArtistGlideRequest.Builder.from(Glide.with(requireContext()), artist)
|
||||||
.generatePalette(requireContext()).build()
|
.generatePalette(requireContext()).build()
|
||||||
.dontAnimate().into(object : RetroMusicColoredTarget(image) {
|
.dontAnimate()
|
||||||
override fun onColorReady(colors: MediaNotificationProcessor) {
|
.into(object : SingleColorTarget(image) {
|
||||||
startPostponedEnterTransition()
|
override fun onColorReady(color: Int) {
|
||||||
setColors(colors)
|
setColors(color)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setColors(color: MediaNotificationProcessor) {
|
private fun setColors(color: Int) {
|
||||||
shuffleAction.applyColor(color.backgroundColor)
|
val finalColor = if (PreferenceUtil.isAdaptiveColor) color
|
||||||
playAction.applyOutlineColor(color.backgroundColor)
|
else ThemeStore.accentColor(requireContext())
|
||||||
|
shuffleAction.applyColor(finalColor)
|
||||||
|
playAction.applyOutlineColor(finalColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onAlbumClick(albumId: Int, view: View) {
|
override fun onAlbumClick(albumId: Int, view: View) {
|
||||||
findNavController().navigate(
|
findNavController().navigate(
|
||||||
R.id.albumDetailsFragment,
|
R.id.albumDetailsFragment,
|
||||||
|
|
|
@ -35,7 +35,6 @@ import code.name.monkey.retromusic.repository.RealRepository
|
||||||
import code.name.monkey.retromusic.service.MusicService
|
import code.name.monkey.retromusic.service.MusicService
|
||||||
import code.name.monkey.retromusic.util.*
|
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.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -75,7 +74,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
||||||
R.id.action_add_to_playlist -> {
|
R.id.action_add_to_playlist -> {
|
||||||
lifecycleScope.launch(IO) {
|
lifecycleScope.launch(IO) {
|
||||||
val playlists = get<RealRepository>().roomPlaylists()
|
val playlists = get<RealRepository>().roomPlaylists()
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Main) {
|
||||||
AddToRetroPlaylist.create(playlists, song)
|
AddToRetroPlaylist.create(playlists, song)
|
||||||
.show(childFragmentManager, "ADD_PLAYLIST")
|
.show(childFragmentManager, "ADD_PLAYLIST")
|
||||||
}
|
}
|
||||||
|
@ -87,7 +86,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.action_save_playing_queue -> {
|
R.id.action_save_playing_queue -> {
|
||||||
CreatePlaylistDialog.create(ArrayList(MusicPlayerRemote.playingQueue))
|
CreateRetroPlaylist.create(ArrayList(MusicPlayerRemote.playingQueue))
|
||||||
.show(childFragmentManager, "ADD_TO_PLAYLIST")
|
.show(childFragmentManager, "ADD_TO_PLAYLIST")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -163,15 +162,17 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
||||||
|
|
||||||
protected open fun toggleFavorite(song: Song) {
|
protected open fun toggleFavorite(song: Song) {
|
||||||
lifecycleScope.launch(IO) {
|
lifecycleScope.launch(IO) {
|
||||||
val playlist: PlaylistEntity = repository.favoritePlaylist().first()
|
val playlist: PlaylistEntity? = repository.favoritePlaylist()
|
||||||
val songEntity = song.toSongEntity(playlist.playListId)
|
if (playlist != null) {
|
||||||
val isFavorite = repository.isFavoriteSong(songEntity).isNotEmpty()
|
val songEntity = song.toSongEntity(playlist.playListId)
|
||||||
if (isFavorite) {
|
val isFavorite = repository.isFavoriteSong(songEntity).isNotEmpty()
|
||||||
repository.removeSongFromPlaylist(songEntity)
|
if (isFavorite) {
|
||||||
} else {
|
repository.removeSongFromPlaylist(songEntity)
|
||||||
repository.insertSongs(listOf(song.toSongEntity(playlist.playListId)))
|
} else {
|
||||||
libraryViewModel.forceReload(Playlists)
|
repository.insertSongs(listOf(song.toSongEntity(playlist.playListId)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
libraryViewModel.forceReload(Playlists)
|
||||||
requireContext().sendBroadcast(Intent(MusicService.FAVORITE_STATE_CHANGED))
|
requireContext().sendBroadcast(Intent(MusicService.FAVORITE_STATE_CHANGED))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,13 +199,18 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
||||||
|
|
||||||
fun updateIsFavorite() {
|
fun updateIsFavorite() {
|
||||||
lifecycleScope.launch(IO) {
|
lifecycleScope.launch(IO) {
|
||||||
val playlist: PlaylistEntity = repository.favoritePlaylist().first()
|
val playlist: PlaylistEntity = repository.favoritePlaylist()
|
||||||
val song = MusicPlayerRemote.currentSong.toSongEntity(playlist.playListId)
|
val song = MusicPlayerRemote.currentSong.toSongEntity(playlist.playListId)
|
||||||
val isFavorite = repository.isFavoriteSong(song).isNotEmpty()
|
val isFavorite = repository.isFavoriteSong(song).isNotEmpty()
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Main) {
|
||||||
val icon = if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
val icon = if (isFavorite) R.drawable.ic_favorite
|
||||||
|
else R.drawable.ic_favorite_border
|
||||||
val drawable =
|
val drawable =
|
||||||
RetroUtil.getTintedVectorDrawable(requireContext(), icon, toolbarIconColor())
|
RetroUtil.getTintedVectorDrawable(
|
||||||
|
requireContext(),
|
||||||
|
icon,
|
||||||
|
toolbarIconColor()
|
||||||
|
)
|
||||||
if (playerToolbar() != null) {
|
if (playerToolbar() != null) {
|
||||||
playerToolbar()?.menu?.findItem(R.id.action_toggle_favorite)
|
playerToolbar()?.menu?.findItem(R.id.action_toggle_favorite)
|
||||||
?.setIcon(drawable)?.title =
|
?.setIcon(drawable)?.title =
|
||||||
|
|
|
@ -16,7 +16,6 @@ package code.name.monkey.retromusic.fragments.home
|
||||||
|
|
||||||
import android.app.ActivityOptions
|
import android.app.ActivityOptions
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.DisplayMetrics
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
|
@ -50,13 +49,6 @@ class HomeFragment :
|
||||||
private val repository by inject<Repository>()
|
private val repository by inject<Repository>()
|
||||||
private val libraryViewModel: LibraryViewModel by sharedViewModel()
|
private val libraryViewModel: LibraryViewModel by sharedViewModel()
|
||||||
|
|
||||||
private val displayMetrics: DisplayMetrics
|
|
||||||
get() {
|
|
||||||
val display = mainActivity.windowManager.defaultDisplay
|
|
||||||
val metrics = DisplayMetrics()
|
|
||||||
display.getMetrics(metrics)
|
|
||||||
return metrics
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
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.interfaces.MusicServiceEventListener
|
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||||
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.repository.RealRepository
|
||||||
|
@ -33,7 +34,7 @@ class PlaylistDetailsViewModel(
|
||||||
|
|
||||||
private fun loadPlaylistSongs(playlist: PlaylistWithSongs) =
|
private fun loadPlaylistSongs(playlist: PlaylistWithSongs) =
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val songs: List<Song> = realRepository.playlistSongs(playlist)
|
val songs: List<Song> = playlist.songs.toSongs()
|
||||||
withContext(Main) { _playListSongs.postValue(songs) }
|
withContext(Main) { _playListSongs.postValue(songs) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
class SongsFragment :
|
class SongsFragment :
|
||||||
AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLayoutManager>(),
|
AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLayoutManager>(),
|
||||||
MainActivityFragmentCallbacks {
|
MainActivityFragmentCallbacks {
|
||||||
|
|
||||||
override fun handleBackPress(): Boolean {
|
override fun handleBackPress(): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package code.name.monkey.retromusic.fragments.songs
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import code.name.monkey.retromusic.model.Song
|
||||||
|
import code.name.monkey.retromusic.repository.SongRepository
|
||||||
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class SongsViewModel(
|
||||||
|
private val songRepository: SongRepository
|
||||||
|
) : ViewModel() {
|
||||||
|
init {
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val songsData = MutableLiveData<List<Song>>().apply { value = mutableListOf() }
|
||||||
|
|
||||||
|
fun getSongList(): LiveData<List<Song>> {
|
||||||
|
return songsData
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update() {
|
||||||
|
viewModelScope.launch(IO) {
|
||||||
|
val songs = songRepository.songs()
|
||||||
|
songsData.postValue(songs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package code.name.monkey.retromusic.glide
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.widget.ImageView
|
||||||
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
|
import code.name.monkey.retromusic.R
|
||||||
|
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTarget
|
||||||
|
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||||
|
import code.name.monkey.retromusic.util.ColorUtil
|
||||||
|
import com.bumptech.glide.request.animation.GlideAnimation
|
||||||
|
|
||||||
|
|
||||||
|
abstract class SingleColorTarget(view: ImageView) : BitmapPaletteTarget(view) {
|
||||||
|
|
||||||
|
protected val defaultFooterColor: Int
|
||||||
|
get() = ATHUtil.resolveColor(view.context, R.attr.colorControlNormal)
|
||||||
|
|
||||||
|
abstract fun onColorReady(color: Int)
|
||||||
|
|
||||||
|
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
|
||||||
|
super.onLoadFailed(e, errorDrawable)
|
||||||
|
onColorReady(defaultFooterColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResourceReady(
|
||||||
|
resource: BitmapPaletteWrapper?,
|
||||||
|
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>?
|
||||||
|
) {
|
||||||
|
super.onResourceReady(resource, glideAnimation)
|
||||||
|
resource?.let {
|
||||||
|
onColorReady(
|
||||||
|
ColorUtil.getColor(
|
||||||
|
it.palette,
|
||||||
|
ATHUtil.resolveColor(view.context, R.attr.colorPrimary)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,9 +35,11 @@ interface Repository {
|
||||||
fun artistsFlow(): Flow<Result<List<Artist>>>
|
fun artistsFlow(): Flow<Result<List<Artist>>>
|
||||||
fun playlistsFlow(): Flow<Result<List<Playlist>>>
|
fun playlistsFlow(): Flow<Result<List<Playlist>>>
|
||||||
fun genresFlow(): Flow<Result<List<Genre>>>
|
fun genresFlow(): Flow<Result<List<Genre>>>
|
||||||
|
fun historySong(): LiveData<List<HistoryEntity>>
|
||||||
|
fun favorites(): LiveData<List<SongEntity>>
|
||||||
suspend fun allAlbums(): List<Album>
|
suspend fun allAlbums(): List<Album>
|
||||||
suspend fun albumById(albumId: Int): Album
|
suspend fun albumByIdAsync(albumId: Int): Album
|
||||||
|
fun albumById(albumId: Int): Album
|
||||||
suspend fun allSongs(): List<Song>
|
suspend fun allSongs(): List<Song>
|
||||||
suspend fun allArtists(): List<Artist>
|
suspend fun allArtists(): List<Artist>
|
||||||
suspend fun albumArtists(): List<Artist>
|
suspend fun albumArtists(): List<Artist>
|
||||||
|
@ -75,7 +77,7 @@ interface Repository {
|
||||||
suspend fun deleteSongsInPlaylist(songs: List<SongEntity>)
|
suspend fun deleteSongsInPlaylist(songs: List<SongEntity>)
|
||||||
suspend fun removeSongFromPlaylist(songEntity: SongEntity)
|
suspend fun removeSongFromPlaylist(songEntity: SongEntity)
|
||||||
suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>)
|
suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>)
|
||||||
suspend fun favoritePlaylist(): List<PlaylistEntity>
|
suspend fun favoritePlaylist(): PlaylistEntity
|
||||||
suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity>
|
suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity>
|
||||||
suspend fun addSongToHistory(currentSong: Song)
|
suspend fun addSongToHistory(currentSong: Song)
|
||||||
suspend fun songPresentInHistory(currentSong: Song): HistoryEntity?
|
suspend fun songPresentInHistory(currentSong: Song): HistoryEntity?
|
||||||
|
@ -88,8 +90,7 @@ interface Repository {
|
||||||
suspend fun deleteSongInPlayCount(playCountEntity: PlayCountEntity)
|
suspend fun deleteSongInPlayCount(playCountEntity: PlayCountEntity)
|
||||||
suspend fun checkSongExistInPlayCount(songId: Int): List<PlayCountEntity>
|
suspend fun checkSongExistInPlayCount(songId: Int): List<PlayCountEntity>
|
||||||
suspend fun playCountSongs(): List<PlayCountEntity>
|
suspend fun playCountSongs(): List<PlayCountEntity>
|
||||||
fun historySong(): LiveData<List<HistoryEntity>>
|
suspend fun blackListPaths(): List<BlackListStoreEntity>
|
||||||
fun favorites(): LiveData<List<SongEntity>>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RealRepository(
|
class RealRepository(
|
||||||
|
@ -103,13 +104,13 @@ class RealRepository(
|
||||||
private val playlistRepository: PlaylistRepository,
|
private val playlistRepository: PlaylistRepository,
|
||||||
private val searchRepository: RealSearchRepository,
|
private val searchRepository: RealSearchRepository,
|
||||||
private val topPlayedRepository: TopPlayedRepository,
|
private val topPlayedRepository: TopPlayedRepository,
|
||||||
private val roomRepository: RoomPlaylistRepository
|
private val roomRepository: RoomRepository
|
||||||
) : Repository {
|
) : Repository {
|
||||||
|
|
||||||
override suspend fun allAlbums(): List<Album> = albumRepository.albums()
|
override suspend fun allAlbums(): List<Album> = albumRepository.albums()
|
||||||
|
|
||||||
override suspend fun albumById(albumId: Int): Album = albumRepository.album(albumId)
|
override suspend fun albumByIdAsync(albumId: Int): Album = albumRepository.album(albumId)
|
||||||
|
override fun albumById(albumId: Int): Album = albumRepository.album(albumId)
|
||||||
override suspend fun allArtists(): List<Artist> = artistRepository.artists()
|
override suspend fun allArtists(): List<Artist> = artistRepository.artists()
|
||||||
|
|
||||||
override suspend fun albumArtists(): List<Artist> = artistRepository.albumArtists()
|
override suspend fun albumArtists(): List<Artist> = artistRepository.albumArtists()
|
||||||
|
@ -130,28 +131,24 @@ class RealRepository(
|
||||||
|
|
||||||
override suspend fun allSongs(): List<Song> = songRepository.songs()
|
override suspend fun allSongs(): List<Song> = songRepository.songs()
|
||||||
|
|
||||||
|
|
||||||
override suspend fun search(query: String?): MutableList<Any> =
|
override suspend fun search(query: String?): MutableList<Any> =
|
||||||
searchRepository.searchAll(context, query)
|
searchRepository.searchAll(context, query)
|
||||||
|
|
||||||
override suspend fun getPlaylistSongs(playlist: Playlist): List<Song> {
|
override suspend fun getPlaylistSongs(playlist: Playlist): List<Song> =
|
||||||
return if (playlist is AbsCustomPlaylist) {
|
if (playlist is AbsCustomPlaylist) {
|
||||||
playlist.songs()
|
playlist.songs()
|
||||||
} else {
|
} else {
|
||||||
PlaylistSongsLoader.getPlaylistSongList(context, playlist.id)
|
PlaylistSongsLoader.getPlaylistSongList(context, playlist.id)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getGenre(genreId: Int): List<Song> = genreRepository.songs(genreId)
|
override suspend fun getGenre(genreId: Int): List<Song> = genreRepository.songs(genreId)
|
||||||
|
|
||||||
|
|
||||||
override suspend fun artistInfo(
|
override suspend fun artistInfo(
|
||||||
name: String,
|
name: String,
|
||||||
lang: String?,
|
lang: String?,
|
||||||
cache: String?
|
cache: String?
|
||||||
): LastFmArtist = lastFMService.artistInfo(name, lang, cache)
|
): LastFmArtist = lastFMService.artistInfo(name, lang, cache)
|
||||||
|
|
||||||
|
|
||||||
override suspend fun albumInfo(
|
override suspend fun albumInfo(
|
||||||
artist: String,
|
artist: String,
|
||||||
album: String
|
album: String
|
||||||
|
@ -193,8 +190,8 @@ class RealRepository(
|
||||||
topAlbumsHome(),
|
topAlbumsHome(),
|
||||||
recentArtistsHome(),
|
recentArtistsHome(),
|
||||||
recentAlbumsHome(),
|
recentAlbumsHome(),
|
||||||
favoritePlaylistHome(),
|
favoritePlaylistHome()
|
||||||
genresHome()
|
// genresHome()
|
||||||
)
|
)
|
||||||
for (section in sections) {
|
for (section in sections) {
|
||||||
if (section.arrayList.isNotEmpty()) {
|
if (section.arrayList.isNotEmpty()) {
|
||||||
|
@ -211,11 +208,10 @@ class RealRepository(
|
||||||
override suspend fun playlistWithSongs(): List<PlaylistWithSongs> =
|
override suspend fun playlistWithSongs(): List<PlaylistWithSongs> =
|
||||||
roomRepository.playlistWithSongs()
|
roomRepository.playlistWithSongs()
|
||||||
|
|
||||||
override suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs): List<Song> {
|
override suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs): List<Song> =
|
||||||
return playlistWithSongs.songs.map {
|
playlistWithSongs.songs.map {
|
||||||
it.toSong()
|
it.toSong()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun insertSongs(songs: List<SongEntity>) =
|
override suspend fun insertSongs(songs: List<SongEntity>) =
|
||||||
roomRepository.insertSongs(songs)
|
roomRepository.insertSongs(songs)
|
||||||
|
@ -243,7 +239,7 @@ class RealRepository(
|
||||||
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) =
|
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) =
|
||||||
roomRepository.deleteSongsFromPlaylist(playlists)
|
roomRepository.deleteSongsFromPlaylist(playlists)
|
||||||
|
|
||||||
override suspend fun favoritePlaylist(): List<PlaylistEntity> =
|
override suspend fun favoritePlaylist(): PlaylistEntity =
|
||||||
roomRepository.favoritePlaylist(context.getString(R.string.favorites))
|
roomRepository.favoritePlaylist(context.getString(R.string.favorites))
|
||||||
|
|
||||||
override suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity> =
|
override suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity> =
|
||||||
|
@ -280,6 +276,9 @@ class RealRepository(
|
||||||
override suspend fun playCountSongs(): List<PlayCountEntity> =
|
override suspend fun playCountSongs(): List<PlayCountEntity> =
|
||||||
roomRepository.playCountSongs()
|
roomRepository.playCountSongs()
|
||||||
|
|
||||||
|
override suspend fun blackListPaths(): List<BlackListStoreEntity> =
|
||||||
|
roomRepository.blackListPaths()
|
||||||
|
|
||||||
override fun historySong(): LiveData<List<HistoryEntity>> =
|
override fun historySong(): LiveData<List<HistoryEntity>> =
|
||||||
roomRepository.historySongs()
|
roomRepository.historySongs()
|
||||||
|
|
||||||
|
@ -328,7 +327,6 @@ class RealRepository(
|
||||||
val songs = favoritePlaylistSongs().map {
|
val songs = favoritePlaylistSongs().map {
|
||||||
it.toSong()
|
it.toSong()
|
||||||
}
|
}
|
||||||
println(songs.size)
|
|
||||||
return Home(songs, FAVOURITES, R.string.favorites)
|
return Home(songs, FAVOURITES, R.string.favorites)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,10 @@ import code.name.monkey.retromusic.db.*
|
||||||
import code.name.monkey.retromusic.model.Song
|
import code.name.monkey.retromusic.model.Song
|
||||||
|
|
||||||
|
|
||||||
interface RoomPlaylistRepository {
|
interface RoomRepository {
|
||||||
|
fun historySongs(): LiveData<List<HistoryEntity>>
|
||||||
|
fun favoritePlaylistLiveData(favorite: String): LiveData<List<SongEntity>>
|
||||||
|
fun insertBlacklistPath(blackListStoreEntity: BlackListStoreEntity)
|
||||||
suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long
|
suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long
|
||||||
suspend fun checkPlaylistExists(playlistName: String): List<PlaylistEntity>
|
suspend fun checkPlaylistExists(playlistName: String): List<PlaylistEntity>
|
||||||
suspend fun playlists(): List<PlaylistEntity>
|
suspend fun playlists(): List<PlaylistEntity>
|
||||||
|
@ -17,7 +20,7 @@ interface RoomPlaylistRepository {
|
||||||
suspend fun renamePlaylistEntity(playlistId: Int, name: String)
|
suspend fun renamePlaylistEntity(playlistId: Int, name: String)
|
||||||
suspend fun deleteSongsInPlaylist(songs: List<SongEntity>)
|
suspend fun deleteSongsInPlaylist(songs: List<SongEntity>)
|
||||||
suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>)
|
suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>)
|
||||||
suspend fun favoritePlaylist(favorite: String): List<PlaylistEntity>
|
suspend fun favoritePlaylist(favorite: String): PlaylistEntity
|
||||||
suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity>
|
suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity>
|
||||||
suspend fun removeSongFromPlaylist(songEntity: SongEntity)
|
suspend fun removeSongFromPlaylist(songEntity: SongEntity)
|
||||||
suspend fun addSongToHistory(currentSong: Song)
|
suspend fun addSongToHistory(currentSong: Song)
|
||||||
|
@ -29,13 +32,18 @@ interface RoomPlaylistRepository {
|
||||||
suspend fun deleteSongInPlayCount(playCountEntity: PlayCountEntity)
|
suspend fun deleteSongInPlayCount(playCountEntity: PlayCountEntity)
|
||||||
suspend fun checkSongExistInPlayCount(songId: Int): List<PlayCountEntity>
|
suspend fun checkSongExistInPlayCount(songId: Int): List<PlayCountEntity>
|
||||||
suspend fun playCountSongs(): List<PlayCountEntity>
|
suspend fun playCountSongs(): List<PlayCountEntity>
|
||||||
fun historySongs(): LiveData<List<HistoryEntity>>
|
suspend fun insertBlacklistPath(blackListStoreEntities: List<BlackListStoreEntity>)
|
||||||
fun favoritePlaylistLiveData(favorite: String): LiveData<List<SongEntity>>
|
suspend fun deleteBlacklistPath(blackListStoreEntity: BlackListStoreEntity)
|
||||||
|
suspend fun clearBlacklist()
|
||||||
|
suspend fun insertBlacklistPathAsync(blackListStoreEntity: BlackListStoreEntity)
|
||||||
|
suspend fun blackListPaths(): List<BlackListStoreEntity>
|
||||||
}
|
}
|
||||||
|
|
||||||
class RealRoomRepository(
|
class RealRoomRepository(
|
||||||
private val playlistDao: PlaylistDao
|
private val playlistDao: PlaylistDao,
|
||||||
) : RoomPlaylistRepository {
|
private val blackListStoreDao: BlackListStoreDao,
|
||||||
|
private val playCountDao: PlayCountDao
|
||||||
|
) : RoomRepository {
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
override suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long =
|
override suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long =
|
||||||
playlistDao.createPlaylist(playlistEntity)
|
playlistDao.createPlaylist(playlistEntity)
|
||||||
|
@ -51,20 +59,18 @@ class RealRoomRepository(
|
||||||
override suspend fun playlistWithSongs(): List<PlaylistWithSongs> =
|
override suspend fun playlistWithSongs(): List<PlaylistWithSongs> =
|
||||||
playlistDao.playlistsWithSongs()
|
playlistDao.playlistsWithSongs()
|
||||||
|
|
||||||
@WorkerThread
|
/* val tempList = ArrayList<SongEntity>(songs)
|
||||||
override suspend fun insertSongs(songs: List<SongEntity>) {
|
|
||||||
/* val tempList = ArrayList<SongEntity>(songs)
|
|
||||||
val existingSongs = songs.map {
|
val existingSongs = songs.map {
|
||||||
playlistDao.checkSongExistsWithPlaylistName(it.playlistCreatorName, it.songId)
|
playlistDao.checkSongExistsWithPlaylistName(it.playlistCreatorName, it.songId)
|
||||||
}.first()
|
}.first()
|
||||||
println("Existing ${existingSongs.size}")
|
println("Existing ${existingSongs.size}")
|
||||||
tempList.removeAll(existingSongs)*/
|
tempList.removeAll(existingSongs)*/
|
||||||
|
@WorkerThread
|
||||||
|
override suspend fun insertSongs(songs: List<SongEntity>) =
|
||||||
playlistDao.insertSongsToPlaylist(songs)
|
playlistDao.insertSongsToPlaylist(songs)
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getSongs(playlistEntity: PlaylistEntity): List<SongEntity> {
|
override suspend fun getSongs(playlistEntity: PlaylistEntity): List<SongEntity> =
|
||||||
return playlistDao.songsFromPlaylist(playlistEntity.playListId)
|
playlistDao.songsFromPlaylist(playlistEntity.playListId)
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun deletePlaylistEntities(playlistEntities: List<PlaylistEntity>) =
|
override suspend fun deletePlaylistEntities(playlistEntities: List<PlaylistEntity>) =
|
||||||
playlistDao.deletePlaylists(playlistEntities)
|
playlistDao.deletePlaylists(playlistEntities)
|
||||||
|
@ -75,14 +81,21 @@ class RealRoomRepository(
|
||||||
override suspend fun deleteSongsInPlaylist(songs: List<SongEntity>) =
|
override suspend fun deleteSongsInPlaylist(songs: List<SongEntity>) =
|
||||||
playlistDao.deleteSongsInPlaylist(songs)
|
playlistDao.deleteSongsInPlaylist(songs)
|
||||||
|
|
||||||
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) {
|
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) =
|
||||||
playlists.forEach {
|
playlists.forEach {
|
||||||
playlistDao.deleteSongsInPlaylist(it.playListId)
|
playlistDao.deleteSongsInPlaylist(it.playListId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun favoritePlaylist(favorite: String): PlaylistEntity {
|
||||||
|
val playlist: PlaylistEntity? = playlistDao.isPlaylistExists(favorite).firstOrNull()
|
||||||
|
return if (playlist != null) {
|
||||||
|
playlist
|
||||||
|
} else {
|
||||||
|
createPlaylist(PlaylistEntity(favorite))
|
||||||
|
playlistDao.isPlaylistExists(favorite).first()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun favoritePlaylist(favorite: String): List<PlaylistEntity> =
|
|
||||||
playlistDao.isPlaylistExists(favorite)
|
|
||||||
|
|
||||||
override suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity> =
|
override suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity> =
|
||||||
playlistDao.isSongExistsInPlaylist(
|
playlistDao.isSongExistsInPlaylist(
|
||||||
|
@ -111,25 +124,41 @@ class RealRoomRepository(
|
||||||
playlistDao.isPlaylistExists(favorite).first().playListId
|
playlistDao.isPlaylistExists(favorite).first().playListId
|
||||||
)
|
)
|
||||||
|
|
||||||
override suspend fun favoritePlaylistSongs(favorite: String): List<SongEntity> {
|
override suspend fun favoritePlaylistSongs(favorite: String): List<SongEntity> =
|
||||||
return if (playlistDao.isPlaylistExists(favorite).isNotEmpty())
|
if (playlistDao.isPlaylistExists(favorite).isNotEmpty())
|
||||||
playlistDao.favoritesSongs(
|
playlistDao.favoritesSongs(
|
||||||
playlistDao.isPlaylistExists(favorite).first().playListId
|
playlistDao.isPlaylistExists(favorite).first().playListId
|
||||||
) else emptyList()
|
) else emptyList()
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun insertSongInPlayCount(playCountEntity: PlayCountEntity) =
|
override suspend fun insertSongInPlayCount(playCountEntity: PlayCountEntity) =
|
||||||
playlistDao.insertSongInPlayCount(playCountEntity)
|
playCountDao.insertSongInPlayCount(playCountEntity)
|
||||||
|
|
||||||
override suspend fun updateSongInPlayCount(playCountEntity: PlayCountEntity) =
|
override suspend fun updateSongInPlayCount(playCountEntity: PlayCountEntity) =
|
||||||
playlistDao.updateSongInPlayCount(playCountEntity)
|
playCountDao.updateSongInPlayCount(playCountEntity)
|
||||||
|
|
||||||
override suspend fun deleteSongInPlayCount(playCountEntity: PlayCountEntity) =
|
override suspend fun deleteSongInPlayCount(playCountEntity: PlayCountEntity) =
|
||||||
playlistDao.deleteSongInPlayCount(playCountEntity)
|
playCountDao.deleteSongInPlayCount(playCountEntity)
|
||||||
|
|
||||||
override suspend fun checkSongExistInPlayCount(songId: Int): List<PlayCountEntity> =
|
override suspend fun checkSongExistInPlayCount(songId: Int): List<PlayCountEntity> =
|
||||||
playlistDao.checkSongExistInPlayCount(songId)
|
playCountDao.checkSongExistInPlayCount(songId)
|
||||||
|
|
||||||
override suspend fun playCountSongs(): List<PlayCountEntity> =
|
override suspend fun playCountSongs(): List<PlayCountEntity> =
|
||||||
playlistDao.playCountSongs()
|
playCountDao.playCountSongs()
|
||||||
|
|
||||||
|
override fun insertBlacklistPath(blackListStoreEntity: BlackListStoreEntity) =
|
||||||
|
blackListStoreDao.insertBlacklistPath(blackListStoreEntity)
|
||||||
|
|
||||||
|
override suspend fun insertBlacklistPath(blackListStoreEntities: List<BlackListStoreEntity>) =
|
||||||
|
blackListStoreDao.insertBlacklistPath(blackListStoreEntities)
|
||||||
|
|
||||||
|
override suspend fun insertBlacklistPathAsync(blackListStoreEntity: BlackListStoreEntity) =
|
||||||
|
blackListStoreDao.insertBlacklistPath(blackListStoreEntity)
|
||||||
|
|
||||||
|
override suspend fun blackListPaths(): List<BlackListStoreEntity> =
|
||||||
|
blackListStoreDao.blackListPaths()
|
||||||
|
|
||||||
|
override suspend fun deleteBlacklistPath(blackListStoreEntity: BlackListStoreEntity) =
|
||||||
|
blackListStoreDao.deleteBlacklistPath(blackListStoreEntity)
|
||||||
|
|
||||||
|
override suspend fun clearBlacklist() = blackListStoreDao.clearBlacklist()
|
||||||
}
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package code.name.monkey.retromusic.util;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.palette.graphics.Palette;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public class ColorUtil {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Palette generatePalette(Bitmap bitmap) {
|
||||||
|
if (bitmap == null) return null;
|
||||||
|
return Palette.from(bitmap).generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ColorInt
|
||||||
|
public static int getColor(@Nullable Palette palette, int fallback) {
|
||||||
|
if (palette != null) {
|
||||||
|
if (palette.getVibrantSwatch() != null) {
|
||||||
|
return palette.getVibrantSwatch().getRgb();
|
||||||
|
} else if (palette.getMutedSwatch() != null) {
|
||||||
|
return palette.getMutedSwatch().getRgb();
|
||||||
|
} else if (palette.getDarkVibrantSwatch() != null) {
|
||||||
|
return palette.getDarkVibrantSwatch().getRgb();
|
||||||
|
} else if (palette.getDarkMutedSwatch() != null) {
|
||||||
|
return palette.getDarkMutedSwatch().getRgb();
|
||||||
|
} else if (palette.getLightVibrantSwatch() != null) {
|
||||||
|
return palette.getLightVibrantSwatch().getRgb();
|
||||||
|
} else if (palette.getLightMutedSwatch() != null) {
|
||||||
|
return palette.getLightMutedSwatch().getRgb();
|
||||||
|
} else if (!palette.getSwatches().isEmpty()) {
|
||||||
|
return Collections.max(palette.getSwatches(), SwatchComparator.getInstance()).getRgb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SwatchComparator implements Comparator<Palette.Swatch> {
|
||||||
|
private static SwatchComparator sInstance;
|
||||||
|
|
||||||
|
static SwatchComparator getInstance() {
|
||||||
|
if (sInstance == null) {
|
||||||
|
sInstance = new SwatchComparator();
|
||||||
|
}
|
||||||
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(Palette.Swatch lhs, Palette.Swatch rhs) {
|
||||||
|
return lhs.getPopulation() - rhs.getPopulation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
org.gradle.jvmargs=-Xmx2048M
|
org.gradle.jvmargs=-Xmx4608m
|
||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
jvmArgs='-Xmx2048m'
|
jvmArgs='-Xmx2048m'
|
||||||
|
|
Loading…
Reference in New Issue