Code refactor
This commit is contained in:
parent
c379342f6a
commit
6881e9a4c1
32 changed files with 411 additions and 173 deletions
|
@ -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.
|
||||
|
||||
### FAQ
|
||||
### ❓ FAQ
|
||||
Please read the FAQ here: https://del.dog/RetroFaq
|
||||
|
||||
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.RoomDatabase
|
||||
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.PlaylistDao
|
||||
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
||||
import code.name.monkey.retromusic.db.RetroDatabase
|
||||
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.playlists.PlaylistDetailsViewModel
|
||||
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.network.networkModule
|
||||
import code.name.monkey.retromusic.repository.*
|
||||
|
@ -35,7 +36,7 @@ private val roomModule = module {
|
|||
super.onOpen(db)
|
||||
GlobalScope.launch(IO) {
|
||||
FilePathUtil.blacklistFilePaths().map {
|
||||
get<PlaylistDao>().insertBlacklistPath(BlackListStoreEntity(it))
|
||||
get<BlackListStoreDao>().insertBlacklistPath(BlackListStoreEntity(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,9 +49,17 @@ private val roomModule = module {
|
|||
get<RetroDatabase>().playlistDao()
|
||||
}
|
||||
|
||||
factory {
|
||||
get<RetroDatabase>().blackListStore()
|
||||
}
|
||||
|
||||
factory {
|
||||
get<RetroDatabase>().playCountDao()
|
||||
}
|
||||
|
||||
single {
|
||||
RealRoomRepository(get())
|
||||
} bind RoomPlaylistRepository::class
|
||||
RealRoomRepository(get(), get(), get())
|
||||
} bind RoomRepository::class
|
||||
}
|
||||
private val mainModule = module {
|
||||
single {
|
||||
|
@ -143,6 +152,10 @@ private val viewModules = module {
|
|||
viewModel {
|
||||
SearchViewModel(get())
|
||||
}
|
||||
|
||||
viewModel {
|
||||
SongsViewModel(get())
|
||||
}
|
||||
}
|
||||
|
||||
val appModules = listOf(mainModule, dataModule, viewModules, networkModule, roomModule)
|
|
@ -34,7 +34,6 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
|
|||
}
|
||||
|
||||
private val repository by inject<Repository>()
|
||||
|
||||
private var blockRequestPermissions = false
|
||||
|
||||
override fun createContentView(): View {
|
||||
|
@ -133,7 +132,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
|
|||
if (id >= 0) {
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
val position = intent.getIntExtra("position", 0)
|
||||
openQueue(repository.albumById(id).songs!!, position, true)
|
||||
openQueue(repository.albumByIdAsync(id).songs!!, position, true)
|
||||
handled = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,17 +4,23 @@ import android.Manifest
|
|||
import android.content.*
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
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.interfaces.MusicServiceEventListener
|
||||
import code.name.monkey.retromusic.repository.RealRepository
|
||||
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.util.*
|
||||
|
||||
abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventListener {
|
||||
|
||||
private val mMusicServiceEventListeners = ArrayList<MusicServiceEventListener>()
|
||||
|
||||
private val repository: RealRepository by inject()
|
||||
private var serviceToken: MusicPlayerRemote.ServiceToken? = null
|
||||
private var musicStateReceiver: MusicStateReceiver? = null
|
||||
private var receiverRegistered: Boolean = false
|
||||
|
@ -93,6 +99,22 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventLis
|
|||
for (listener in mMusicServiceEventListeners) {
|
||||
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() {
|
||||
|
|
|
@ -73,7 +73,6 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
|||
setContentView(createContentView())
|
||||
chooseFragmentForTheme()
|
||||
setupSlidingUpPanel()
|
||||
addMusicServiceEventListener(libraryViewModel)
|
||||
|
||||
setupBottomSheet()
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ import android.view.MenuItem
|
|||
import android.view.View
|
||||
import android.view.animation.OvershootInterpolator
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
|
@ -182,11 +181,9 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() {
|
|||
saveFab = findViewById(R.id.saveTags)
|
||||
getIntentExtras()
|
||||
|
||||
lifecycleScope.launchWhenCreated {
|
||||
songPaths = getSongPaths()
|
||||
if (songPaths!!.isEmpty()) {
|
||||
finish()
|
||||
}
|
||||
songPaths = getSongPaths()
|
||||
if (songPaths!!.isEmpty()) {
|
||||
finish()
|
||||
}
|
||||
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) {
|
||||
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 paths = ArrayList<String>(songs!!.size)
|
||||
for (song in songs) {
|
||||
|
|
|
@ -88,7 +88,7 @@ class SongTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
|||
writeValuesToFiles(fieldKeyValueMap, null)
|
||||
}
|
||||
|
||||
override suspend fun getSongPaths(): List<String> {
|
||||
override fun getSongPaths(): List<String> {
|
||||
val paths = ArrayList<String>(1)
|
||||
paths.add(songRepository.song(id).data)
|
||||
return paths
|
||||
|
|
|
@ -154,13 +154,11 @@ class PlaylistAdapter(
|
|||
|
||||
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
|
||||
init {
|
||||
|
||||
image?.apply {
|
||||
val iconPadding =
|
||||
activity.resources.getDimensionPixelSize(R.dimen.list_item_image_icon_padding)
|
||||
setPadding(iconPadding, iconPadding, iconPadding, iconPadding)
|
||||
}
|
||||
|
||||
menu?.setOnClickListener { view ->
|
||||
val popupMenu = PopupMenu(activity, view)
|
||||
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")
|
||||
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(
|
||||
entities = [PlaylistEntity::class, SongEntity::class, HistoryEntity::class, PlayCountEntity::class, BlackListStoreEntity::class],
|
||||
version = 18,
|
||||
version = 19,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class RetroDatabase : RoomDatabase() {
|
||||
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)
|
||||
.setItems(playlistNames.toTypedArray()) { _, which ->
|
||||
if (which == 0) {
|
||||
CreateRetroPlaylist().show(requireActivity().supportFragmentManager, "Dialog")
|
||||
CreateRetroPlaylist.create(songs).show(requireActivity().supportFragmentManager, "Dialog")
|
||||
} else {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val songEntities = songs.toSongEntity(playlistEntities[which - 1])
|
||||
|
|
|
@ -5,14 +5,18 @@ import android.os.Bundle
|
|||
import android.text.TextUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.Toast
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import code.name.monkey.retromusic.EXTRA_SONG
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.db.PlaylistEntity
|
||||
import code.name.monkey.retromusic.extensions.colorButtons
|
||||
import code.name.monkey.retromusic.extensions.extraNotNull
|
||||
import code.name.monkey.retromusic.extensions.materialDialog
|
||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||
import code.name.monkey.retromusic.fragments.ReloadType.Playlists
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.repository.RealRepository
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
|
@ -25,8 +29,24 @@ import org.koin.androidx.viewmodel.ext.android.sharedViewModel
|
|||
class CreateRetroPlaylist : DialogFragment() {
|
||||
private val repository by inject<RealRepository>()
|
||||
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 {
|
||||
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 playlistContainer: TextInputLayout = view.actionNewPlaylistContainer
|
||||
return materialDialog(R.string.new_playlist_title)
|
||||
|
@ -38,13 +58,14 @@ class CreateRetroPlaylist : DialogFragment() {
|
|||
if (!TextUtils.isEmpty(playlistName)) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
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)
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Playlist exists", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
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.floatingactionbutton.ExtendedFloatingActionButton
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
|
||||
fun Int.ripAlpha(): Int {
|
||||
|
@ -145,10 +144,6 @@ fun TextInputLayout.accentColor() {
|
|||
isHintAnimationEnabled = true
|
||||
}
|
||||
|
||||
fun TextInputEditText.accentColor() {
|
||||
|
||||
}
|
||||
|
||||
fun AppCompatImageView.accentColor(): Int {
|
||||
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()
|
||||
}
|
||||
lifecycleScope.launch(IO) {
|
||||
val songs = repository.recentSongs()
|
||||
val songs = repository.playCountSongs().map {
|
||||
it.toSong()
|
||||
}
|
||||
withContext(Main) { songAdapter.swapDataSet(songs) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,7 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
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.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||
import code.name.monkey.retromusic.model.*
|
||||
import code.name.monkey.retromusic.repository.RealRepository
|
||||
|
@ -51,7 +49,7 @@ class LibraryViewModel(
|
|||
artists.value = loadArtists.await()
|
||||
playlists.value = loadPlaylists.await()
|
||||
roomPlaylists.value = loadPlaylistsWithSongs.await()
|
||||
genres.value = loadGenres.await()
|
||||
//genres.value = loadGenres.await()
|
||||
}
|
||||
|
||||
private val loadHome: Deferred<List<Home>>
|
||||
|
@ -86,7 +84,6 @@ class LibraryViewModel(
|
|||
|
||||
|
||||
fun forceReload(reloadType: ReloadType) = viewModelScope.launch {
|
||||
println(reloadType)
|
||||
when (reloadType) {
|
||||
Songs -> songs.value = loadSongs.await()
|
||||
Albums -> albums.value = loadAlbums.await()
|
||||
|
@ -121,22 +118,7 @@ class LibraryViewModel(
|
|||
|
||||
override fun 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() {
|
||||
|
|
|
@ -14,6 +14,7 @@ import androidx.navigation.fragment.navArgs
|
|||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.common.ATHToolbarActivity.getToolbarBackgroundColor
|
||||
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||
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.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.SortOrder
|
||||
import code.name.monkey.retromusic.model.Album
|
||||
|
@ -77,9 +79,9 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
|
|||
toolbar.title = null
|
||||
|
||||
postponeEnterTransition()
|
||||
detailsViewModel.getAlbum().observe(viewLifecycleOwner, Observer {
|
||||
showAlbum(it)
|
||||
detailsViewModel.getAlbum2().observe(viewLifecycleOwner, Observer {
|
||||
startPostponedEnterTransition()
|
||||
showAlbum(it)
|
||||
})
|
||||
detailsViewModel.getArtist().observe(viewLifecycleOwner, Observer {
|
||||
loadArtistImage(it)
|
||||
|
@ -232,16 +234,18 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
|
|||
.build()
|
||||
.dontAnimate()
|
||||
.dontTransform()
|
||||
.into(object : RetroMusicColoredTarget(image) {
|
||||
override fun onColorReady(colors: MediaNotificationProcessor) {
|
||||
setColors(colors)
|
||||
.into(object : SingleColorTarget(image) {
|
||||
override fun onColorReady(color: Int) {
|
||||
setColors(color)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun setColors(color: MediaNotificationProcessor) {
|
||||
shuffleAction.applyColor(color.backgroundColor)
|
||||
playAction.applyOutlineColor(color.backgroundColor)
|
||||
private fun setColors(color: Int) {
|
||||
val finalColor =
|
||||
if (PreferenceUtil.isAdaptiveColor) color else ThemeStore.accentColor(requireContext())
|
||||
shuffleAction.applyColor(finalColor)
|
||||
playAction.applyOutlineColor(finalColor)
|
||||
}
|
||||
|
||||
override fun onAlbumClick(albumId: Int, view: View) {
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
package code.name.monkey.retromusic.fragments.albums
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.*
|
||||
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||
import code.name.monkey.retromusic.model.Album
|
||||
import code.name.monkey.retromusic.model.Artist
|
||||
import code.name.monkey.retromusic.network.model.LastFmAlbum
|
||||
import code.name.monkey.retromusic.repository.RealRepository
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
@ -24,7 +21,11 @@ class AlbumDetailsViewModel(
|
|||
private val _lastFmAlbum = MutableLiveData<LastFmAlbum>()
|
||||
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 getAlbumInfo(): LiveData<LastFmAlbum> = _lastFmAlbum
|
||||
fun getMoreAlbums(): LiveData<List<Album>> = _moreAlbums
|
||||
|
@ -33,17 +34,22 @@ class AlbumDetailsViewModel(
|
|||
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")
|
||||
_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 ?: "-")
|
||||
_lastFmAlbum.postValue(lastFmAlbum)
|
||||
}
|
||||
|
||||
fun loadArtist(artistId: Int) = viewModelScope.launch(Dispatchers.IO) {
|
||||
fun loadArtist(artistId: Int) = viewModelScope.launch(IO) {
|
||||
val artist = realRepository.artistById(artistId)
|
||||
_artist.postValue(artist)
|
||||
|
||||
|
@ -53,8 +59,8 @@ class AlbumDetailsViewModel(
|
|||
}
|
||||
|
||||
private val loadAlbumAsync: Deferred<Album?>
|
||||
get() = viewModelScope.async(Dispatchers.IO) {
|
||||
realRepository.albumById(albumId)
|
||||
get() = viewModelScope.async(IO) {
|
||||
realRepository.albumByIdAsync(albumId)
|
||||
}
|
||||
|
||||
override fun onMediaStoreChanged() {
|
||||
|
|
|
@ -17,6 +17,7 @@ import androidx.navigation.fragment.navArgs
|
|||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
|
||||
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.base.AbsMainActivityFragment
|
||||
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.model.Artist
|
||||
import code.name.monkey.retromusic.network.model.LastFmArtist
|
||||
import code.name.monkey.retromusic.repository.RealRepository
|
||||
import code.name.monkey.retromusic.util.CustomArtistImageUtil
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||
import com.bumptech.glide.Glide
|
||||
import kotlinx.android.synthetic.main.fragment_artist_content.*
|
||||
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) {
|
||||
ArtistGlideRequest.Builder.from(Glide.with(requireContext()), artist)
|
||||
.generatePalette(requireContext()).build()
|
||||
.dontAnimate().into(object : RetroMusicColoredTarget(image) {
|
||||
override fun onColorReady(colors: MediaNotificationProcessor) {
|
||||
startPostponedEnterTransition()
|
||||
setColors(colors)
|
||||
.dontAnimate()
|
||||
.into(object : SingleColorTarget(image) {
|
||||
override fun onColorReady(color: Int) {
|
||||
setColors(color)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun setColors(color: MediaNotificationProcessor) {
|
||||
shuffleAction.applyColor(color.backgroundColor)
|
||||
playAction.applyOutlineColor(color.backgroundColor)
|
||||
private fun setColors(color: Int) {
|
||||
val finalColor = if (PreferenceUtil.isAdaptiveColor) color
|
||||
else ThemeStore.accentColor(requireContext())
|
||||
shuffleAction.applyColor(finalColor)
|
||||
playAction.applyOutlineColor(finalColor)
|
||||
}
|
||||
|
||||
|
||||
override fun onAlbumClick(albumId: Int, view: View) {
|
||||
findNavController().navigate(
|
||||
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.util.*
|
||||
import kotlinx.android.synthetic.main.shadow_statusbar_toolbar.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -75,7 +74,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
R.id.action_add_to_playlist -> {
|
||||
lifecycleScope.launch(IO) {
|
||||
val playlists = get<RealRepository>().roomPlaylists()
|
||||
withContext(Dispatchers.Main) {
|
||||
withContext(Main) {
|
||||
AddToRetroPlaylist.create(playlists, song)
|
||||
.show(childFragmentManager, "ADD_PLAYLIST")
|
||||
}
|
||||
|
@ -87,7 +86,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
return true
|
||||
}
|
||||
R.id.action_save_playing_queue -> {
|
||||
CreatePlaylistDialog.create(ArrayList(MusicPlayerRemote.playingQueue))
|
||||
CreateRetroPlaylist.create(ArrayList(MusicPlayerRemote.playingQueue))
|
||||
.show(childFragmentManager, "ADD_TO_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
|
@ -163,15 +162,17 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
|
||||
protected open fun toggleFavorite(song: Song) {
|
||||
lifecycleScope.launch(IO) {
|
||||
val playlist: PlaylistEntity = repository.favoritePlaylist().first()
|
||||
val songEntity = song.toSongEntity(playlist.playListId)
|
||||
val isFavorite = repository.isFavoriteSong(songEntity).isNotEmpty()
|
||||
if (isFavorite) {
|
||||
repository.removeSongFromPlaylist(songEntity)
|
||||
} else {
|
||||
repository.insertSongs(listOf(song.toSongEntity(playlist.playListId)))
|
||||
libraryViewModel.forceReload(Playlists)
|
||||
val playlist: PlaylistEntity? = repository.favoritePlaylist()
|
||||
if (playlist != null) {
|
||||
val songEntity = song.toSongEntity(playlist.playListId)
|
||||
val isFavorite = repository.isFavoriteSong(songEntity).isNotEmpty()
|
||||
if (isFavorite) {
|
||||
repository.removeSongFromPlaylist(songEntity)
|
||||
} else {
|
||||
repository.insertSongs(listOf(song.toSongEntity(playlist.playListId)))
|
||||
}
|
||||
}
|
||||
libraryViewModel.forceReload(Playlists)
|
||||
requireContext().sendBroadcast(Intent(MusicService.FAVORITE_STATE_CHANGED))
|
||||
}
|
||||
}
|
||||
|
@ -198,13 +199,18 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
|
||||
fun updateIsFavorite() {
|
||||
lifecycleScope.launch(IO) {
|
||||
val playlist: PlaylistEntity = repository.favoritePlaylist().first()
|
||||
val playlist: PlaylistEntity = repository.favoritePlaylist()
|
||||
val song = MusicPlayerRemote.currentSong.toSongEntity(playlist.playListId)
|
||||
val isFavorite = repository.isFavoriteSong(song).isNotEmpty()
|
||||
withContext(Dispatchers.Main) {
|
||||
val icon = if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
||||
withContext(Main) {
|
||||
val icon = if (isFavorite) R.drawable.ic_favorite
|
||||
else R.drawable.ic_favorite_border
|
||||
val drawable =
|
||||
RetroUtil.getTintedVectorDrawable(requireContext(), icon, toolbarIconColor())
|
||||
RetroUtil.getTintedVectorDrawable(
|
||||
requireContext(),
|
||||
icon,
|
||||
toolbarIconColor()
|
||||
)
|
||||
if (playerToolbar() != null) {
|
||||
playerToolbar()?.menu?.findItem(R.id.action_toggle_favorite)
|
||||
?.setIcon(drawable)?.title =
|
||||
|
|
|
@ -16,7 +16,6 @@ package code.name.monkey.retromusic.fragments.home
|
|||
|
||||
import android.app.ActivityOptions
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.View
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.Observer
|
||||
|
@ -50,13 +49,6 @@ class HomeFragment :
|
|||
private val repository by inject<Repository>()
|
||||
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?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
|
|
@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
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.model.Song
|
||||
import code.name.monkey.retromusic.repository.RealRepository
|
||||
|
@ -33,7 +34,7 @@ class PlaylistDetailsViewModel(
|
|||
|
||||
private fun loadPlaylistSongs(playlist: PlaylistWithSongs) =
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val songs: List<Song> = realRepository.playlistSongs(playlist)
|
||||
val songs: List<Song> = playlist.songs.toSongs()
|
||||
withContext(Main) { _playListSongs.postValue(songs) }
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import code.name.monkey.retromusic.util.PreferenceUtil
|
|||
class SongsFragment :
|
||||
AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLayoutManager>(),
|
||||
MainActivityFragmentCallbacks {
|
||||
|
||||
override fun handleBackPress(): Boolean {
|
||||
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 playlistsFlow(): Flow<Result<List<Playlist>>>
|
||||
fun genresFlow(): Flow<Result<List<Genre>>>
|
||||
|
||||
fun historySong(): LiveData<List<HistoryEntity>>
|
||||
fun favorites(): LiveData<List<SongEntity>>
|
||||
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 allArtists(): List<Artist>
|
||||
suspend fun albumArtists(): List<Artist>
|
||||
|
@ -75,7 +77,7 @@ interface Repository {
|
|||
suspend fun deleteSongsInPlaylist(songs: List<SongEntity>)
|
||||
suspend fun removeSongFromPlaylist(songEntity: SongEntity)
|
||||
suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>)
|
||||
suspend fun favoritePlaylist(): List<PlaylistEntity>
|
||||
suspend fun favoritePlaylist(): PlaylistEntity
|
||||
suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity>
|
||||
suspend fun addSongToHistory(currentSong: Song)
|
||||
suspend fun songPresentInHistory(currentSong: Song): HistoryEntity?
|
||||
|
@ -88,8 +90,7 @@ interface Repository {
|
|||
suspend fun deleteSongInPlayCount(playCountEntity: PlayCountEntity)
|
||||
suspend fun checkSongExistInPlayCount(songId: Int): List<PlayCountEntity>
|
||||
suspend fun playCountSongs(): List<PlayCountEntity>
|
||||
fun historySong(): LiveData<List<HistoryEntity>>
|
||||
fun favorites(): LiveData<List<SongEntity>>
|
||||
suspend fun blackListPaths(): List<BlackListStoreEntity>
|
||||
}
|
||||
|
||||
class RealRepository(
|
||||
|
@ -103,13 +104,13 @@ class RealRepository(
|
|||
private val playlistRepository: PlaylistRepository,
|
||||
private val searchRepository: RealSearchRepository,
|
||||
private val topPlayedRepository: TopPlayedRepository,
|
||||
private val roomRepository: RoomPlaylistRepository
|
||||
private val roomRepository: RoomRepository
|
||||
) : Repository {
|
||||
|
||||
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 albumArtists(): List<Artist> = artistRepository.albumArtists()
|
||||
|
@ -130,28 +131,24 @@ class RealRepository(
|
|||
|
||||
override suspend fun allSongs(): List<Song> = songRepository.songs()
|
||||
|
||||
|
||||
override suspend fun search(query: String?): MutableList<Any> =
|
||||
searchRepository.searchAll(context, query)
|
||||
|
||||
override suspend fun getPlaylistSongs(playlist: Playlist): List<Song> {
|
||||
return if (playlist is AbsCustomPlaylist) {
|
||||
override suspend fun getPlaylistSongs(playlist: Playlist): List<Song> =
|
||||
if (playlist is AbsCustomPlaylist) {
|
||||
playlist.songs()
|
||||
} else {
|
||||
PlaylistSongsLoader.getPlaylistSongList(context, playlist.id)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getGenre(genreId: Int): List<Song> = genreRepository.songs(genreId)
|
||||
|
||||
|
||||
override suspend fun artistInfo(
|
||||
name: String,
|
||||
lang: String?,
|
||||
cache: String?
|
||||
): LastFmArtist = lastFMService.artistInfo(name, lang, cache)
|
||||
|
||||
|
||||
override suspend fun albumInfo(
|
||||
artist: String,
|
||||
album: String
|
||||
|
@ -193,8 +190,8 @@ class RealRepository(
|
|||
topAlbumsHome(),
|
||||
recentArtistsHome(),
|
||||
recentAlbumsHome(),
|
||||
favoritePlaylistHome(),
|
||||
genresHome()
|
||||
favoritePlaylistHome()
|
||||
// genresHome()
|
||||
)
|
||||
for (section in sections) {
|
||||
if (section.arrayList.isNotEmpty()) {
|
||||
|
@ -211,11 +208,10 @@ class RealRepository(
|
|||
override suspend fun playlistWithSongs(): List<PlaylistWithSongs> =
|
||||
roomRepository.playlistWithSongs()
|
||||
|
||||
override suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs): List<Song> {
|
||||
return playlistWithSongs.songs.map {
|
||||
override suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs): List<Song> =
|
||||
playlistWithSongs.songs.map {
|
||||
it.toSong()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun insertSongs(songs: List<SongEntity>) =
|
||||
roomRepository.insertSongs(songs)
|
||||
|
@ -243,7 +239,7 @@ class RealRepository(
|
|||
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) =
|
||||
roomRepository.deleteSongsFromPlaylist(playlists)
|
||||
|
||||
override suspend fun favoritePlaylist(): List<PlaylistEntity> =
|
||||
override suspend fun favoritePlaylist(): PlaylistEntity =
|
||||
roomRepository.favoritePlaylist(context.getString(R.string.favorites))
|
||||
|
||||
override suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity> =
|
||||
|
@ -280,6 +276,9 @@ class RealRepository(
|
|||
override suspend fun playCountSongs(): List<PlayCountEntity> =
|
||||
roomRepository.playCountSongs()
|
||||
|
||||
override suspend fun blackListPaths(): List<BlackListStoreEntity> =
|
||||
roomRepository.blackListPaths()
|
||||
|
||||
override fun historySong(): LiveData<List<HistoryEntity>> =
|
||||
roomRepository.historySongs()
|
||||
|
||||
|
@ -328,7 +327,6 @@ class RealRepository(
|
|||
val songs = favoritePlaylistSongs().map {
|
||||
it.toSong()
|
||||
}
|
||||
println(songs.size)
|
||||
return Home(songs, FAVOURITES, R.string.favorites)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,10 @@ import code.name.monkey.retromusic.db.*
|
|||
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 checkPlaylistExists(playlistName: String): List<PlaylistEntity>
|
||||
suspend fun playlists(): List<PlaylistEntity>
|
||||
|
@ -17,7 +20,7 @@ interface RoomPlaylistRepository {
|
|||
suspend fun renamePlaylistEntity(playlistId: Int, name: String)
|
||||
suspend fun deleteSongsInPlaylist(songs: List<SongEntity>)
|
||||
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 removeSongFromPlaylist(songEntity: SongEntity)
|
||||
suspend fun addSongToHistory(currentSong: Song)
|
||||
|
@ -29,13 +32,18 @@ interface RoomPlaylistRepository {
|
|||
suspend fun deleteSongInPlayCount(playCountEntity: PlayCountEntity)
|
||||
suspend fun checkSongExistInPlayCount(songId: Int): List<PlayCountEntity>
|
||||
suspend fun playCountSongs(): List<PlayCountEntity>
|
||||
fun historySongs(): LiveData<List<HistoryEntity>>
|
||||
fun favoritePlaylistLiveData(favorite: String): LiveData<List<SongEntity>>
|
||||
suspend fun insertBlacklistPath(blackListStoreEntities: List<BlackListStoreEntity>)
|
||||
suspend fun deleteBlacklistPath(blackListStoreEntity: BlackListStoreEntity)
|
||||
suspend fun clearBlacklist()
|
||||
suspend fun insertBlacklistPathAsync(blackListStoreEntity: BlackListStoreEntity)
|
||||
suspend fun blackListPaths(): List<BlackListStoreEntity>
|
||||
}
|
||||
|
||||
class RealRoomRepository(
|
||||
private val playlistDao: PlaylistDao
|
||||
) : RoomPlaylistRepository {
|
||||
private val playlistDao: PlaylistDao,
|
||||
private val blackListStoreDao: BlackListStoreDao,
|
||||
private val playCountDao: PlayCountDao
|
||||
) : RoomRepository {
|
||||
@WorkerThread
|
||||
override suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long =
|
||||
playlistDao.createPlaylist(playlistEntity)
|
||||
|
@ -51,20 +59,18 @@ class RealRoomRepository(
|
|||
override suspend fun playlistWithSongs(): List<PlaylistWithSongs> =
|
||||
playlistDao.playlistsWithSongs()
|
||||
|
||||
@WorkerThread
|
||||
override suspend fun insertSongs(songs: List<SongEntity>) {
|
||||
/* val tempList = ArrayList<SongEntity>(songs)
|
||||
/* val tempList = ArrayList<SongEntity>(songs)
|
||||
val existingSongs = songs.map {
|
||||
playlistDao.checkSongExistsWithPlaylistName(it.playlistCreatorName, it.songId)
|
||||
}.first()
|
||||
println("Existing ${existingSongs.size}")
|
||||
tempList.removeAll(existingSongs)*/
|
||||
@WorkerThread
|
||||
override suspend fun insertSongs(songs: List<SongEntity>) =
|
||||
playlistDao.insertSongsToPlaylist(songs)
|
||||
}
|
||||
|
||||
override suspend fun getSongs(playlistEntity: PlaylistEntity): List<SongEntity> {
|
||||
return playlistDao.songsFromPlaylist(playlistEntity.playListId)
|
||||
}
|
||||
override suspend fun getSongs(playlistEntity: PlaylistEntity): List<SongEntity> =
|
||||
playlistDao.songsFromPlaylist(playlistEntity.playListId)
|
||||
|
||||
override suspend fun deletePlaylistEntities(playlistEntities: List<PlaylistEntity>) =
|
||||
playlistDao.deletePlaylists(playlistEntities)
|
||||
|
@ -75,14 +81,21 @@ class RealRoomRepository(
|
|||
override suspend fun deleteSongsInPlaylist(songs: List<SongEntity>) =
|
||||
playlistDao.deleteSongsInPlaylist(songs)
|
||||
|
||||
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) {
|
||||
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) =
|
||||
playlists.forEach {
|
||||
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> =
|
||||
playlistDao.isSongExistsInPlaylist(
|
||||
|
@ -111,25 +124,41 @@ class RealRoomRepository(
|
|||
playlistDao.isPlaylistExists(favorite).first().playListId
|
||||
)
|
||||
|
||||
override suspend fun favoritePlaylistSongs(favorite: String): List<SongEntity> {
|
||||
return if (playlistDao.isPlaylistExists(favorite).isNotEmpty())
|
||||
override suspend fun favoritePlaylistSongs(favorite: String): List<SongEntity> =
|
||||
if (playlistDao.isPlaylistExists(favorite).isNotEmpty())
|
||||
playlistDao.favoritesSongs(
|
||||
playlistDao.isPlaylistExists(favorite).first().playListId
|
||||
) else emptyList()
|
||||
}
|
||||
|
||||
override suspend fun insertSongInPlayCount(playCountEntity: PlayCountEntity) =
|
||||
playlistDao.insertSongInPlayCount(playCountEntity)
|
||||
playCountDao.insertSongInPlayCount(playCountEntity)
|
||||
|
||||
override suspend fun updateSongInPlayCount(playCountEntity: PlayCountEntity) =
|
||||
playlistDao.updateSongInPlayCount(playCountEntity)
|
||||
playCountDao.updateSongInPlayCount(playCountEntity)
|
||||
|
||||
override suspend fun deleteSongInPlayCount(playCountEntity: PlayCountEntity) =
|
||||
playlistDao.deleteSongInPlayCount(playCountEntity)
|
||||
playCountDao.deleteSongInPlayCount(playCountEntity)
|
||||
|
||||
override suspend fun checkSongExistInPlayCount(songId: Int): List<PlayCountEntity> =
|
||||
playlistDao.checkSongExistInPlayCount(songId)
|
||||
playCountDao.checkSongExistInPlayCount(songId)
|
||||
|
||||
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.parallel=true
|
||||
jvmArgs='-Xmx2048m'
|
||||
|
|
Loading…
Reference in a new issue