🙆🏻Ohh got AsyncTask removed finally
And Favorite playlist added yay
This commit is contained in:
parent
d5d77afaaf
commit
069d45e8df
9 changed files with 135 additions and 127 deletions
|
@ -20,7 +20,6 @@ import code.name.monkey.appthemehelper.ThemeStore
|
|||
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
|
||||
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
||||
import com.amitshekhar.DebugDB
|
||||
import com.anjlab.android.iab.v3.BillingProcessor
|
||||
import com.anjlab.android.iab.v3.TransactionDetails
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
|
@ -33,7 +32,7 @@ class App : MultiDexApplication() {
|
|||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
instance = this
|
||||
DebugDB.getAddressLog();
|
||||
|
||||
startKoin {
|
||||
androidContext(this@App)
|
||||
modules(appModules)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package code.name.monkey.retromusic
|
||||
|
||||
import code.name.monkey.retromusic.db.PlaylistDatabase
|
||||
import androidx.room.Room
|
||||
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
||||
import code.name.monkey.retromusic.repository.RealRoomPlaylistRepository
|
||||
import code.name.monkey.retromusic.repository.RoomPlaylistRepository
|
||||
import code.name.monkey.retromusic.db.RetroDatabase
|
||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||
import code.name.monkey.retromusic.fragments.albums.AlbumDetailsViewModel
|
||||
import code.name.monkey.retromusic.fragments.artists.ArtistDetailsViewModel
|
||||
|
@ -18,6 +17,22 @@ import org.koin.androidx.viewmodel.dsl.viewModel
|
|||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
|
||||
private val roomModule = module {
|
||||
single {
|
||||
Room.databaseBuilder(androidContext(), RetroDatabase::class.java, "playlist.db")
|
||||
.allowMainThreadQueries()
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
}
|
||||
|
||||
factory {
|
||||
get<RetroDatabase>().playlistDao()
|
||||
}
|
||||
|
||||
single {
|
||||
RealRoomRepository(get())
|
||||
} bind RoomPlaylistRepository::class
|
||||
}
|
||||
private val mainModule = module {
|
||||
single {
|
||||
androidContext().contentResolver
|
||||
|
@ -70,14 +85,6 @@ private val dataModule = module {
|
|||
get()
|
||||
)
|
||||
}
|
||||
|
||||
single {
|
||||
PlaylistDatabase.getDatabase(get()).playlistDao()
|
||||
}
|
||||
|
||||
single {
|
||||
RealRoomPlaylistRepository(get())
|
||||
} bind RoomPlaylistRepository::class
|
||||
}
|
||||
|
||||
private val viewModules = module {
|
||||
|
@ -119,4 +126,4 @@ private val viewModules = module {
|
|||
}
|
||||
}
|
||||
|
||||
val appModules = listOf(mainModule, dataModule, viewModules, networkModule)
|
||||
val appModules = listOf(mainModule, dataModule, viewModules, networkModule, roomModule)
|
|
@ -26,8 +26,8 @@ interface PlaylistDao {
|
|||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertSongs(songEntities: List<SongEntity>)
|
||||
|
||||
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistName AND id = :songId")
|
||||
suspend fun checkSongExistsWithPlaylistName(playlistName: String, songId: Int): List<SongEntity>
|
||||
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistId AND id = :songId")
|
||||
suspend fun checkSongExistsWithPlaylistId(playlistId: Int, songId: Int): List<SongEntity>
|
||||
|
||||
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistId")
|
||||
suspend fun getSongs(playlistId: Int): List<SongEntity>
|
||||
|
@ -41,4 +41,6 @@ interface PlaylistDao {
|
|||
@Delete
|
||||
suspend fun removeSongsFromPlaylist(songs: List<SongEntity>)
|
||||
|
||||
@Query("DELETE FROM SongEntity WHERE playlist_creator_id = :playlistId AND id = :songId")
|
||||
fun removeSong(playlistId: Int, songId: Int)
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package code.name.monkey.retromusic.db
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
|
||||
@Database(
|
||||
entities = [PlaylistEntity::class, SongEntity::class],
|
||||
version = 8,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class PlaylistDatabase : RoomDatabase() {
|
||||
abstract fun playlistDao(): PlaylistDao
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var INSTANCE: PlaylistDatabase? = null
|
||||
|
||||
fun getDatabase(
|
||||
context: Context
|
||||
): PlaylistDatabase {
|
||||
return INSTANCE ?: synchronized(this) {
|
||||
val instance = Room.databaseBuilder(
|
||||
context.applicationContext,
|
||||
PlaylistDatabase::class.java,
|
||||
"playlists.db"
|
||||
).fallbackToDestructiveMigration().build()
|
||||
INSTANCE = instance
|
||||
instance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package code.name.monkey.retromusic.db
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
|
||||
@Database(
|
||||
entities = [PlaylistEntity::class, SongEntity::class],
|
||||
version = 8,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class RetroDatabase : RoomDatabase() {
|
||||
abstract fun playlistDao(): PlaylistDao
|
||||
}
|
|
@ -65,7 +65,7 @@ class RemoveSongFromPlaylistDialog : DialogFragment() {
|
|||
.setMessage(pair.second)
|
||||
.setPositiveButton(R.string.remove_action) { _, _ ->
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
repository.removeSongFromPlaylist(songs)
|
||||
repository.removeSongsFromPlaylist(songs)
|
||||
}
|
||||
/* PlaylistsUtil.removeFromPlaylist(
|
||||
requireContext(),
|
||||
|
|
|
@ -4,7 +4,6 @@ import android.annotation.SuppressLint
|
|||
import android.content.ContentUris
|
||||
import android.content.Intent
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.os.AsyncTask
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
|
@ -22,8 +21,10 @@ import code.name.monkey.retromusic.EXTRA_ARTIST_ID
|
|||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity
|
||||
import code.name.monkey.retromusic.activities.tageditor.SongTagEditorActivity
|
||||
import code.name.monkey.retromusic.db.PlaylistEntity
|
||||
import code.name.monkey.retromusic.dialogs.*
|
||||
import code.name.monkey.retromusic.extensions.hide
|
||||
import code.name.monkey.retromusic.extensions.whichFragment
|
||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
|
@ -31,20 +32,22 @@ import code.name.monkey.retromusic.interfaces.PaletteColorHolder
|
|||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.model.lyrics.Lyrics
|
||||
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
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.android.ext.android.get
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragment(layout),
|
||||
Toolbar.OnMenuItemClickListener, PaletteColorHolder, PlayerAlbumCoverFragment.Callbacks {
|
||||
|
||||
private var updateIsFavoriteTask: AsyncTask<*, *, *>? = null
|
||||
private var updateLyricsAsyncTask: AsyncTask<*, *, *>? = null
|
||||
private var playerAlbumCoverFragment: PlayerAlbumCoverFragment? = null
|
||||
protected val libraryViewModel by sharedViewModel<LibraryViewModel>()
|
||||
|
||||
|
@ -70,7 +73,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
return true
|
||||
}
|
||||
R.id.action_add_to_playlist -> {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
lifecycleScope.launch(IO) {
|
||||
val playlists = get<RealRepository>().roomPlaylists()
|
||||
withContext(Dispatchers.Main) {
|
||||
AddToRetroPlaylist.create(playlists, song)
|
||||
|
@ -159,7 +162,16 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
}
|
||||
|
||||
protected open fun toggleFavorite(song: Song) {
|
||||
MusicUtil.toggleFavorite(requireActivity(), song)
|
||||
lifecycleScope.launch(IO) {
|
||||
val playlist: PlaylistEntity = repository.favoritePlaylist().first()
|
||||
val songEntity = song.toSongEntity(playlist.playListId)
|
||||
if (repository.isFavoriteSong(songEntity).isNotEmpty()) {
|
||||
repository.removeSongFromPlaylist(songEntity)
|
||||
} else {
|
||||
repository.insertSongs(listOf(song.toSongEntity(playlist.playListId)))
|
||||
}
|
||||
requireContext().sendBroadcast(Intent(MusicService.FAVORITE_STATE_CHANGED))
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun playerToolbar(): Toolbar?
|
||||
|
@ -181,85 +193,65 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
updateIsFavorite()
|
||||
updateLyrics()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
if (updateIsFavoriteTask != null && !updateIsFavoriteTask!!.isCancelled) {
|
||||
updateIsFavoriteTask!!.cancel(true)
|
||||
}
|
||||
if (updateLyricsAsyncTask != null && !updateLyricsAsyncTask!!.isCancelled) {
|
||||
updateLyricsAsyncTask!!.cancel(true)
|
||||
}
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
fun updateIsFavorite() {
|
||||
if (updateIsFavoriteTask != null) {
|
||||
updateIsFavoriteTask!!.cancel(false)
|
||||
}
|
||||
updateIsFavoriteTask = object : AsyncTask<Song, Void, Boolean>() {
|
||||
override fun doInBackground(vararg params: Song): Boolean {
|
||||
return MusicUtil.isFavorite(requireActivity(), params[0])
|
||||
}
|
||||
|
||||
override fun onPostExecute(isFavorite: Boolean) {
|
||||
val res = if (isFavorite)
|
||||
R.drawable.ic_favorite
|
||||
else
|
||||
R.drawable.ic_favorite_border
|
||||
|
||||
lifecycleScope.launch(IO) {
|
||||
val playlist: PlaylistEntity = repository.favoritePlaylist().first()
|
||||
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
|
||||
val drawable =
|
||||
RetroUtil.getTintedVectorDrawable(requireContext(), res, toolbarIconColor())
|
||||
if (playerToolbar() != null && playerToolbar()!!.menu.findItem(R.id.action_toggle_favorite) != null)
|
||||
playerToolbar()!!.menu.findItem(R.id.action_toggle_favorite).setIcon(drawable)
|
||||
.title =
|
||||
if (isFavorite) getString(R.string.action_remove_from_favorites) else getString(
|
||||
R.string.action_add_to_favorites
|
||||
)
|
||||
RetroUtil.getTintedVectorDrawable(requireContext(), icon, toolbarIconColor())
|
||||
if (playerToolbar() != null) {
|
||||
playerToolbar()?.menu?.findItem(R.id.action_toggle_favorite)
|
||||
?.setIcon(drawable)?.title =
|
||||
if (isFavorite) getString(R.string.action_remove_from_favorites)
|
||||
else getString(R.string.action_add_to_favorites)
|
||||
}
|
||||
}
|
||||
}.execute(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private fun updateLyrics() {
|
||||
if (updateLyricsAsyncTask != null) updateLyricsAsyncTask!!.cancel(false)
|
||||
|
||||
updateLyricsAsyncTask = object : AsyncTask<Song, Void, Lyrics>() {
|
||||
override fun onPreExecute() {
|
||||
super.onPreExecute()
|
||||
setLyrics(null)
|
||||
setLyrics(null)
|
||||
lifecycleScope.launch(IO) {
|
||||
val song = MusicPlayerRemote.currentSong
|
||||
val lyrics = try {
|
||||
var data: String? = LyricUtil.getStringFromFile(song.title, song.artistName)
|
||||
if (TextUtils.isEmpty(data)) {
|
||||
data = MusicUtil.getLyrics(song)
|
||||
if (TextUtils.isEmpty(data)) {
|
||||
null
|
||||
} else {
|
||||
Lyrics.parse(song, data)
|
||||
}
|
||||
} else Lyrics.parse(song, data!!)
|
||||
} catch (err: FileNotFoundException) {
|
||||
null
|
||||
}
|
||||
|
||||
override fun doInBackground(vararg params: Song): Lyrics? {
|
||||
try {
|
||||
var data: String? =
|
||||
LyricUtil.getStringFromFile(params[0].title, params[0].artistName)
|
||||
return if (TextUtils.isEmpty(data)) {
|
||||
data = MusicUtil.getLyrics(params[0])
|
||||
return if (TextUtils.isEmpty(data)) {
|
||||
null
|
||||
} else {
|
||||
Lyrics.parse(params[0], data)
|
||||
}
|
||||
} else Lyrics.parse(params[0], data!!)
|
||||
} catch (err: FileNotFoundException) {
|
||||
return null
|
||||
}
|
||||
withContext(Main) {
|
||||
setLyrics(lyrics)
|
||||
}
|
||||
|
||||
override fun onPostExecute(l: Lyrics?) {
|
||||
setLyrics(l)
|
||||
}
|
||||
|
||||
override fun onCancelled(s: Lyrics?) {
|
||||
onPostExecute(null)
|
||||
}
|
||||
}.execute(MusicPlayerRemote.currentSong)
|
||||
}
|
||||
}
|
||||
|
||||
open fun setLyrics(l: Lyrics?) {
|
||||
}
|
||||
|
||||
private val repository by inject<RealRepository>()
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
lifecycleScope.launch(IO) {
|
||||
if (repository.checkPlaylistExists(getString(R.string.favorites)).isEmpty()) {
|
||||
repository.createPlaylist(PlaylistEntity(getString(R.string.favorites)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
if (PreferenceUtil.isFullScreenMode &&
|
||||
|
@ -267,8 +259,7 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
|
|||
) {
|
||||
view.findViewById<View>(R.id.status_bar).visibility = View.GONE
|
||||
}
|
||||
playerAlbumCoverFragment =
|
||||
childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment?
|
||||
playerAlbumCoverFragment = whichFragment(R.id.playerAlbumCoverFragment)
|
||||
playerAlbumCoverFragment?.setCallbacks(this)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
|
|
|
@ -114,9 +114,15 @@ interface Repository {
|
|||
|
||||
suspend fun renameRoomPlaylist(playlistId: Int, name: String)
|
||||
|
||||
suspend fun removeSongFromPlaylist(songs: List<SongEntity>)
|
||||
suspend fun removeSongsFromPlaylist(songs: List<SongEntity>)
|
||||
|
||||
suspend fun removeSongFromPlaylist(songEntity: SongEntity)
|
||||
|
||||
suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>)
|
||||
|
||||
suspend fun favoritePlaylist(): List<PlaylistEntity>
|
||||
|
||||
suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity>
|
||||
}
|
||||
|
||||
class RealRepository(
|
||||
|
@ -215,11 +221,11 @@ class RealRepository(
|
|||
override suspend fun homeSections(): List<Home> {
|
||||
val homeSections = mutableListOf<Home>()
|
||||
val sections = listOf(
|
||||
suggestionsHome(),
|
||||
topArtistsHome(),
|
||||
topAlbumsHome(),
|
||||
recentArtistsHome(),
|
||||
recentAlbumsHome(),
|
||||
suggestionsHome(),
|
||||
favoritePlaylistHome()
|
||||
)
|
||||
for (section in sections) {
|
||||
|
@ -264,18 +270,27 @@ class RealRepository(
|
|||
override suspend fun renameRoomPlaylist(playlistId: Int, name: String) =
|
||||
roomPlaylistRepository.renamePlaylistEntity(playlistId, name)
|
||||
|
||||
override suspend fun removeSongFromPlaylist(songs: List<SongEntity>) =
|
||||
override suspend fun removeSongsFromPlaylist(songs: List<SongEntity>) =
|
||||
roomPlaylistRepository.removeSongsFromPlaylist(songs)
|
||||
|
||||
override suspend fun removeSongFromPlaylist(songEntity: SongEntity) =
|
||||
roomPlaylistRepository.removeSongFromPlaylist(songEntity)
|
||||
|
||||
|
||||
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) =
|
||||
roomPlaylistRepository.deleteSongsFromPlaylist(playlists)
|
||||
|
||||
override suspend fun favoritePlaylist(): List<PlaylistEntity> =
|
||||
roomPlaylistRepository.favoritePlaylist(context.getString(R.string.favorites))
|
||||
|
||||
override suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity> =
|
||||
roomPlaylistRepository.isFavoriteSong(songEntity)
|
||||
|
||||
override suspend fun suggestionsHome(): Home {
|
||||
val songs =
|
||||
NotPlayedPlaylist().songs().shuffled().takeIf {
|
||||
it.size > 9
|
||||
} ?: emptyList()
|
||||
println(songs.size)
|
||||
return Home(songs, SUGGESTIONS)
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,12 @@ interface RoomPlaylistRepository {
|
|||
suspend fun renamePlaylistEntity(playlistId: Int, name: String)
|
||||
suspend fun removeSongsFromPlaylist(songs: List<SongEntity>)
|
||||
suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>)
|
||||
suspend fun favoritePlaylist(favorite: String): List<PlaylistEntity>
|
||||
suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity>
|
||||
suspend fun removeSongFromPlaylist(songEntity: SongEntity)
|
||||
}
|
||||
|
||||
class RealRoomPlaylistRepository(
|
||||
class RealRoomRepository(
|
||||
private val playlistDao: PlaylistDao
|
||||
) : RoomPlaylistRepository {
|
||||
@WorkerThread
|
||||
|
@ -68,4 +71,16 @@ class RealRoomPlaylistRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun favoritePlaylist(favorite: String): List<PlaylistEntity> =
|
||||
playlistDao.checkPlaylistExists(favorite)
|
||||
|
||||
override suspend fun isFavoriteSong(songEntity: SongEntity): List<SongEntity> =
|
||||
playlistDao.checkSongExistsWithPlaylistId(
|
||||
songEntity.playlistCreatorId,
|
||||
songEntity.id
|
||||
)
|
||||
|
||||
override suspend fun removeSongFromPlaylist(songEntity: SongEntity) =
|
||||
playlistDao.removeSong(songEntity.playlistCreatorId, songEntity.id)
|
||||
|
||||
}
|
Loading…
Reference in a new issue