Code refactor

This commit is contained in:
Hemanth S 2020-09-11 00:52:10 +05:30
parent 5ebeb9c587
commit 0ef83c7136
23 changed files with 156 additions and 94 deletions

View file

@ -143,7 +143,7 @@ dependencies {
implementation 'com.afollestad:material-cab:0.1.12' implementation 'com.afollestad:material-cab:0.1.12'
def kotlin_coroutines_version = "1.3.8" def kotlin_coroutines_version = "1.3.8"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.0" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
@ -171,6 +171,6 @@ dependencies {
implementation 'org.jsoup:jsoup:1.11.1' implementation 'org.jsoup:jsoup:1.11.1'
implementation 'me.zhanghai.android.fastscroll:library:1.1.0' implementation 'me.zhanghai.android.fastscroll:library:1.1.0'
implementation 'me.jorgecastillo:androidcolorx:0.2.0' implementation 'me.jorgecastillo:androidcolorx:0.2.0'
implementation 'org.jsoup:jsoup:1.11.1'
debugImplementation 'com.amitshekhar.android:debug-db:1.0.6' debugImplementation 'com.amitshekhar.android:debug-db:1.0.6'
} }

View file

@ -65,6 +65,9 @@ private val roomModule = module {
.fallbackToDestructiveMigration() .fallbackToDestructiveMigration()
.build() .build()
} }
factory {
get<RetroDatabase>().lyricsDao()
}
factory { factory {
get<RetroDatabase>().playlistDao() get<RetroDatabase>().playlistDao()
@ -83,7 +86,7 @@ private val roomModule = module {
} }
single { single {
RealRoomRepository(get(), get(), get(), get()) RealRoomRepository(get(), get(), get(), get(), get())
} bind RoomRepository::class } bind RoomRepository::class
} }
private val mainModule = module { private val mainModule = module {

View file

@ -92,7 +92,7 @@ class AlbumCoverPagerAdapter(
albumCover = view.findViewById(R.id.player_image) albumCover = view.findViewById(R.id.player_image)
albumCover.setOnClickListener { albumCover.setOnClickListener {
LyricsDialog().show(childFragmentManager, "LyricsDialog") LyricsDialog().show(childFragmentManager, "LyricsDialog")
//showLyricsDialog() showLyricsDialog()
} }
return view return view
} }

View file

@ -0,0 +1,18 @@
package code.name.monkey.retromusic.db
import androidx.room.*
@Dao
interface LyricsDao {
@Query("SELECT * FROM LyricsEntity WHERE songId =:songId LIMIT 1")
fun lyricsWithSongId(songId: Int): LyricsEntity?
@Insert
fun insertLyrics(lyricsEntity: LyricsEntity)
@Delete
fun deleteLyrics(lyricsEntity: LyricsEntity)
@Update
fun updateLyrics(lyricsEntity: LyricsEntity)
}

View file

@ -0,0 +1,10 @@
package code.name.monkey.retromusic.db
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity
class LyricsEntity(
@PrimaryKey val songId: Int,
val lyrics: String
)

View file

@ -18,10 +18,10 @@ interface PlaylistDao {
suspend fun playlists(): List<PlaylistEntity> suspend fun playlists(): List<PlaylistEntity>
@Query("DELETE FROM SongEntity WHERE playlist_creator_id = :playlistId") @Query("DELETE FROM SongEntity WHERE playlist_creator_id = :playlistId")
suspend fun deleteSongsInPlaylist(playlistId: Int) suspend fun deletePlaylistSongs(playlistId: Int)
@Query("DELETE FROM SongEntity WHERE playlist_creator_id = :playlistId AND id = :songId") @Query("DELETE FROM SongEntity WHERE playlist_creator_id = :playlistId AND id = :songId")
suspend fun removeSongFromPlaylist(playlistId: Int, songId: Int) suspend fun deleteSongFromPlaylist(playlistId: Int, songId: Int)
@Transaction @Transaction
@Query("SELECT * FROM PlaylistEntity") @Query("SELECT * FROM PlaylistEntity")
@ -34,7 +34,7 @@ interface PlaylistDao {
suspend fun isSongExistsInPlaylist(playlistId: Int, songId: Int): List<SongEntity> suspend fun isSongExistsInPlaylist(playlistId: Int, songId: Int): List<SongEntity>
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistId") @Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistId")
suspend fun songsFromPlaylist(playlistId: Int): List<SongEntity> fun songsFromPlaylist(playlistId: Int): LiveData<List<SongEntity>>
@Delete @Delete
suspend fun deletePlaylist(playlistEntity: PlaylistEntity) suspend fun deletePlaylist(playlistEntity: PlaylistEntity)
@ -43,7 +43,7 @@ interface PlaylistDao {
suspend fun deletePlaylists(playlistEntities: List<PlaylistEntity>) suspend fun deletePlaylists(playlistEntities: List<PlaylistEntity>)
@Delete @Delete
suspend fun deleteSongsInPlaylist(songs: List<SongEntity>) suspend fun deletePlaylistSongs(songs: List<SongEntity>)
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id= :playlistId") @Query("SELECT * FROM SongEntity WHERE playlist_creator_id= :playlistId")
@ -53,5 +53,4 @@ interface PlaylistDao {
fun favoritesSongs(playlistId: Int): List<SongEntity> fun favoritesSongs(playlistId: Int): List<SongEntity>
} }

View file

@ -4,8 +4,8 @@ import androidx.room.Database
import androidx.room.RoomDatabase 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, LyricsEntity::class],
version = 20, version = 21,
exportSchema = false exportSchema = false
) )
abstract class RetroDatabase : RoomDatabase() { abstract class RetroDatabase : RoomDatabase() {
@ -13,4 +13,5 @@ abstract class RetroDatabase : RoomDatabase() {
abstract fun blackListStore(): BlackListStoreDao abstract fun blackListStore(): BlackListStoreDao
abstract fun playCountDao(): PlayCountDao abstract fun playCountDao(): PlayCountDao
abstract fun historyDao(): HistoryDao abstract fun historyDao(): HistoryDao
abstract fun lyricsDao(): LyricsDao
} }

View file

@ -63,7 +63,6 @@ class DeleteSongsDialog : DialogFragment() {
} }
MusicUtil.deleteTracks(requireActivity(), songs) MusicUtil.deleteTracks(requireActivity(), songs)
libraryViewModel.deleteTracks(songs) libraryViewModel.deleteTracks(songs)
} }
.create() .create()
.colorButtons() .colorButtons()

View file

@ -7,6 +7,8 @@ import android.view.ViewGroup
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.accentTextColor
import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.network.Result import code.name.monkey.retromusic.network.Result
import code.name.monkey.retromusic.repository.Repository import code.name.monkey.retromusic.repository.Repository
@ -34,16 +36,23 @@ class LyricsDialog : DialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val song = MusicPlayerRemote.currentSong
dialogTitle.text = song.title
syncedLyrics.accentTextColor()
lifecycleScope.launch(IO) { lifecycleScope.launch(IO) {
val result: Result<String> = repository.lyrics( val result: Result<String> = repository.lyrics(
MusicPlayerRemote.currentSong.artistName, song.artistName,
MusicPlayerRemote.currentSong.title song.title
) )
withContext(Main) { withContext(Main) {
when (result) { when (result) {
is Result.Error -> println("Error") is Result.Error -> progressBar.hide()
is Result.Loading -> println("Loading") is Result.Loading -> println("Loading")
is Result.Success -> lyricsText.text = result.data is Result.Success -> {
progressBar.hide()
lyricsText.text = result.data
}
} }
} }
} }

View file

@ -22,8 +22,10 @@ import android.graphics.drawable.Drawable
import android.widget.Button import android.widget.Button
import android.widget.CheckBox import android.widget.CheckBox
import android.widget.SeekBar import android.widget.SeekBar
import androidx.annotation.* import androidx.annotation.AttrRes
import androidx.appcompat.content.res.AppCompatResources import androidx.annotation.CheckResult
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ -97,6 +99,10 @@ fun Button.accentTextColor() {
setTextColor(ThemeStore.accentColor(App.getContext())) setTextColor(ThemeStore.accentColor(App.getContext()))
} }
fun MaterialButton.accentTextColor() {
setTextColor(ThemeStore.accentColor(App.getContext()))
}
fun SeekBar.applyColor(@ColorInt color: Int) { fun SeekBar.applyColor(@ColorInt color: Int) {
thumbTintList = ColorStateList.valueOf(color) thumbTintList = ColorStateList.valueOf(color)
progressTintList = ColorStateList.valueOf(color) progressTintList = ColorStateList.valueOf(color)

View file

@ -185,7 +185,7 @@ class LibraryViewModel(
} }
fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) = viewModelScope.launch(IO) { fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) = viewModelScope.launch(IO) {
repository.deleteSongsFromPlaylist(playlists) repository.deletePlaylistSongs(playlists)
} }
fun deleteRoomPlaylist(playlists: List<PlaylistEntity>) = viewModelScope.launch(IO) { fun deleteRoomPlaylist(playlists: List<PlaylistEntity>) = viewModelScope.launch(IO) {
@ -209,7 +209,7 @@ class LibraryViewModel(
fun importPlaylists() = viewModelScope.launch(IO) { fun importPlaylists() = viewModelScope.launch(IO) {
val playlists = repository.fetchLegacyPlaylist() val playlists = repository.fetchLegacyPlaylist()
playlists.forEach { playlist -> playlists.forEach { playlist ->
val playlistEntity = repository.checkPlaylistExists(playlist.name).firstOrNull(); val playlistEntity = repository.checkPlaylistExists(playlist.name).firstOrNull()
if (playlistEntity != null) { if (playlistEntity != null) {
val songEntities = playlist.getSongs().map { val songEntities = playlist.getSongs().map {
it.toSongEntity(playlistEntity.playListId) it.toSongEntity(playlistEntity.playListId)
@ -228,8 +228,9 @@ class LibraryViewModel(
fun deleteTracks(songs: List<Song>) = viewModelScope.launch(IO) { fun deleteTracks(songs: List<Song>) = viewModelScope.launch(IO) {
repository.deleteSongs(songs) repository.deleteSongs(songs)
fetchPlaylists()
loadLibraryContent()
} }
} }
enum class ReloadType { enum class ReloadType {

View file

@ -5,7 +5,6 @@ import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.lifecycle.Observer
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -13,6 +12,7 @@ import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter import code.name.monkey.retromusic.adapter.song.SongAdapter
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.extensions.dipToPix import code.name.monkey.retromusic.extensions.dipToPix
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
@ -49,17 +49,13 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
setUpRecyclerView() setUpRecyclerView()
viewModel.getSongs().observe(viewLifecycleOwner, Observer { viewModel.getSongs().observe(viewLifecycleOwner, {
songs(it) songs(it.toSongs())
}) })
} }
private fun setUpRecyclerView() { private fun setUpRecyclerView() {
recyclerView.layoutManager = LinearLayoutManager(requireContext()) recyclerView.layoutManager = LinearLayoutManager(requireContext())
/*if (playlist is AbsCustomPlaylist) {
adapter = SongAdapter(requireActivity(), ArrayList(), R.layout.item_list, null)
recyclerView.adapter = adapter
} else {*/
recyclerViewDragDropManager = RecyclerViewDragDropManager() recyclerViewDragDropManager = RecyclerViewDragDropManager()
val animator = RefactoredDefaultItemAnimator() val animator = RefactoredDefaultItemAnimator()
adapter = adapter =

View file

@ -3,16 +3,11 @@ package code.name.monkey.retromusic.fragments.playlists
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
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.db.SongEntity
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
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class PlaylistDetailsViewModel( class PlaylistDetailsViewModel(
private val realRepository: RealRepository, private val realRepository: RealRepository,
@ -26,17 +21,8 @@ class PlaylistDetailsViewModel(
fun getPlaylist(): LiveData<PlaylistWithSongs> = _playlist fun getPlaylist(): LiveData<PlaylistWithSongs> = _playlist
fun getSongs(): LiveData<List<Song>> = _playListSongs fun getSongs(): LiveData<List<SongEntity>> = realRepository.playlistSongs(playlist.playlistEntity)
init {
loadPlaylistSongs(playlist)
}
private fun loadPlaylistSongs(playlist: PlaylistWithSongs) =
viewModelScope.launch(Dispatchers.IO) {
val songs: List<Song> = playlist.songs.toSongs()
withContext(Main) { _playListSongs.postValue(songs) }
}
override fun onMediaStoreChanged() { override fun onMediaStoreChanged() {
/*if (playlist !is AbsCustomPlaylist) { /*if (playlist !is AbsCustomPlaylist) {

View file

@ -63,9 +63,8 @@ public class CategoryInfo implements Parcelable {
Songs(R.id.action_song, R.string.songs, R.drawable.ic_audiotrack), Songs(R.id.action_song, R.string.songs, R.drawable.ic_audiotrack),
Albums(R.id.action_album, R.string.albums, R.drawable.ic_album), Albums(R.id.action_album, R.string.albums, R.drawable.ic_album),
Artists(R.id.action_artist, R.string.artists, R.drawable.ic_artist), Artists(R.id.action_artist, R.string.artists, R.drawable.ic_artist),
Playlists(R.id.action_playlist, R.string.playlists, R.drawable.ic_playlist_play), Playlists(R.id.action_playlist, R.string.playlists, (R.drawable.ic_queue_music)),
Genres(R.id.action_genre, R.string.genres, R.drawable.ic_guitar), Genres(R.id.action_genre, R.string.genres, R.drawable.ic_guitar),
Queue(R.id.action_playing_queue, R.string.queue, R.drawable.ic_queue_music),
Folder(R.id.action_folder, R.string.folders, R.drawable.ic_folder); Folder(R.id.action_folder, R.string.folders, R.drawable.ic_folder);
public final int icon; public final int icon;

View file

@ -21,5 +21,5 @@ package code.name.monkey.retromusic.network
sealed class Result<out R> { sealed class Result<out R> {
data class Success<out T>(val data: T) : Result<T>() data class Success<out T>(val data: T) : Result<T>()
object Loading : Result<Nothing>() object Loading : Result<Nothing>()
object Error : Result<Nothing>() data class Error(val error: Exception) : Result<Nothing>()
} }

View file

@ -4,7 +4,7 @@ import android.content.Context
import code.name.monkey.retromusic.App import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.BuildConfig import code.name.monkey.retromusic.BuildConfig
import code.name.monkey.retromusic.network.conversion.LyricsConverterFactory import code.name.monkey.retromusic.network.conversion.LyricsConverterFactory
import com.google.gson.Gson import com.google.gson.GsonBuilder
import okhttp3.Cache import okhttp3.Cache
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -14,6 +14,7 @@ import retrofit2.converter.gson.GsonConverterFactory
import java.io.File import java.io.File
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
fun provideDefaultCache(): Cache? { fun provideDefaultCache(): Cache? {
val cacheDir = File(App.getContext().cacheDir.absolutePath, "/okhttp-lastfm/") val cacheDir = File(App.getContext().cacheDir.absolutePath, "/okhttp-lastfm/")
if (cacheDir.mkdirs() || cacheDir.isDirectory) { if (cacheDir.mkdirs() || cacheDir.isDirectory) {
@ -48,7 +49,7 @@ fun headerInterceptor(context: Context): Interceptor {
fun provideOkHttp(context: Context, cache: Cache): OkHttpClient { fun provideOkHttp(context: Context, cache: Cache): OkHttpClient {
return OkHttpClient.Builder() return OkHttpClient.Builder()
.addNetworkInterceptor(logInterceptor()) .addNetworkInterceptor(logInterceptor())
.addInterceptor(headerInterceptor(context)) //.addInterceptor(headerInterceptor(context))
.connectTimeout(1, TimeUnit.SECONDS) .connectTimeout(1, TimeUnit.SECONDS)
.readTimeout(1, TimeUnit.SECONDS) .readTimeout(1, TimeUnit.SECONDS)
.cache(cache) .cache(cache)
@ -56,9 +57,12 @@ fun provideOkHttp(context: Context, cache: Cache): OkHttpClient {
} }
fun provideLastFmRetrofit(client: OkHttpClient): Retrofit { fun provideLastFmRetrofit(client: OkHttpClient): Retrofit {
val gson = GsonBuilder()
.setLenient()
.create()
return Retrofit.Builder() return Retrofit.Builder()
.baseUrl("https://ws.audioscrobbler.com/2.0/") .baseUrl("https://ws.audioscrobbler.com/2.0/")
.addConverterFactory(GsonConverterFactory.create(Gson())) .addConverterFactory(GsonConverterFactory.create(gson))
.callFactory { request -> client.newCall(request) } .callFactory { request -> client.newCall(request) }
.build() .build()
} }

View file

@ -42,6 +42,7 @@ interface Repository {
fun favorites(): LiveData<List<SongEntity>> fun favorites(): LiveData<List<SongEntity>>
fun observableHistorySongs(): LiveData<List<HistoryEntity>> fun observableHistorySongs(): LiveData<List<HistoryEntity>>
fun albumById(albumId: Int): Album fun albumById(albumId: Int): Album
fun playlistSongs(playlistEntity: PlaylistEntity): LiveData<List<SongEntity>>
suspend fun fetchAlbums(): List<Album> suspend fun fetchAlbums(): List<Album>
suspend fun albumByIdAsync(albumId: Int): Album suspend fun albumByIdAsync(albumId: Int): Album
suspend fun allSongs(): List<Song> suspend fun allSongs(): List<Song>
@ -80,7 +81,7 @@ interface Repository {
suspend fun renameRoomPlaylist(playlistId: Int, name: String) suspend fun renameRoomPlaylist(playlistId: Int, name: String)
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 deletePlaylistSongs(playlists: List<PlaylistEntity>)
suspend fun favoritePlaylist(): 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)
@ -117,7 +118,8 @@ class RealRepository(
override suspend fun lyrics(artist: String, title: String): Result<String> = try { override suspend fun lyrics(artist: String, title: String): Result<String> = try {
Success(lyricsRestService.getLyrics(artist, title)) Success(lyricsRestService.getLyrics(artist, title))
} catch (e: Exception) { } catch (e: Exception) {
Error println(e)
Error(e)
} }
override suspend fun deleteSongs(songs: List<Song>) = roomRepository.deleteSongs(songs) override suspend fun deleteSongs(songs: List<Song>) = roomRepository.deleteSongs(songs)
@ -169,7 +171,7 @@ class RealRepository(
Success(lastFMService.artistInfo(name, lang, cache)) Success(lastFMService.artistInfo(name, lang, cache))
} catch (e: Exception) { } catch (e: Exception) {
println(e) println(e)
Error Error(e)
} }
} }
@ -182,7 +184,7 @@ class RealRepository(
Success(lastFmAlbum) Success(lastFmAlbum)
} catch (e: Exception) { } catch (e: Exception) {
println(e) println(e)
Error Error(e)
} }
} }
@ -206,7 +208,7 @@ class RealRepository(
} }
} }
if (homeSections.isEmpty()) { if (homeSections.isEmpty()) {
homes.value = Error homes.value = Error(Exception(Throwable("No items")))
} else { } else {
homes.value = Success(homeSections) homes.value = Success(homeSections)
} }
@ -244,6 +246,9 @@ class RealRepository(
it.toSong() it.toSong()
} }
override fun playlistSongs(playlistEntity: PlaylistEntity): LiveData<List<SongEntity>> =
roomRepository.getSongs(playlistEntity)
override suspend fun insertSongs(songs: List<SongEntity>) = override suspend fun insertSongs(songs: List<SongEntity>) =
roomRepository.insertSongs(songs) roomRepository.insertSongs(songs)
@ -267,8 +272,8 @@ class RealRepository(
override suspend fun removeSongFromPlaylist(songEntity: SongEntity) = override suspend fun removeSongFromPlaylist(songEntity: SongEntity) =
roomRepository.removeSongFromPlaylist(songEntity) roomRepository.removeSongFromPlaylist(songEntity)
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) = override suspend fun deletePlaylistSongs(playlists: List<PlaylistEntity>) =
roomRepository.deleteSongsFromPlaylist(playlists) roomRepository.deletePlaylistSongs(playlists)
override suspend fun favoritePlaylist(): PlaylistEntity = override suspend fun favoritePlaylist(): PlaylistEntity =
roomRepository.favoritePlaylist(context.getString(R.string.favorites)) roomRepository.favoritePlaylist(context.getString(R.string.favorites))
@ -368,7 +373,7 @@ class RealRepository(
emit(Loading) emit(Loading)
val data = songRepository.songs() val data = songRepository.songs()
if (data.isEmpty()) { if (data.isEmpty()) {
emit(Error) emit(Error(Exception(Throwable("No items"))))
} else { } else {
emit(Success(data)) emit(Success(data))
} }
@ -378,7 +383,7 @@ class RealRepository(
emit(Loading) emit(Loading)
val data = albumRepository.albums() val data = albumRepository.albums()
if (data.isEmpty()) { if (data.isEmpty()) {
emit(Error) emit(Error(Exception(Throwable("No items"))))
} else { } else {
emit(Success(data)) emit(Success(data))
} }
@ -388,7 +393,7 @@ class RealRepository(
emit(Loading) emit(Loading)
val data = artistRepository.artists() val data = artistRepository.artists()
if (data.isEmpty()) { if (data.isEmpty()) {
emit(Error) emit(Error(Exception(Throwable("No items"))))
} else { } else {
emit(Success(data)) emit(Success(data))
} }
@ -398,7 +403,7 @@ class RealRepository(
emit(Loading) emit(Loading)
val data = playlistRepository.playlists() val data = playlistRepository.playlists()
if (data.isEmpty()) { if (data.isEmpty()) {
emit(Error) emit(Error(Exception(Throwable("No items"))))
} else { } else {
emit(Success(data)) emit(Success(data))
} }
@ -408,7 +413,7 @@ class RealRepository(
emit(Loading) emit(Loading)
val data = genreRepository.genres() val data = genreRepository.genres()
if (data.isEmpty()) { if (data.isEmpty()) {
emit(Error) emit(Error(Exception(Throwable("No items"))))
} else { } else {
emit(Success(data)) emit(Success(data))
} }

View file

@ -11,16 +11,16 @@ interface RoomRepository {
fun favoritePlaylistLiveData(favorite: String): LiveData<List<SongEntity>> fun favoritePlaylistLiveData(favorite: String): LiveData<List<SongEntity>>
fun insertBlacklistPath(blackListStoreEntity: BlackListStoreEntity) fun insertBlacklistPath(blackListStoreEntity: BlackListStoreEntity)
fun observableHistorySongs(): LiveData<List<HistoryEntity>> fun observableHistorySongs(): LiveData<List<HistoryEntity>>
fun getSongs(playlistEntity: PlaylistEntity): LiveData<List<SongEntity>>
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>
suspend fun playlistWithSongs(): List<PlaylistWithSongs> suspend fun playlistWithSongs(): List<PlaylistWithSongs>
suspend fun insertSongs(songs: List<SongEntity>) suspend fun insertSongs(songs: List<SongEntity>)
suspend fun getSongs(playlistEntity: PlaylistEntity): List<SongEntity>
suspend fun deletePlaylistEntities(playlistEntities: List<PlaylistEntity>) suspend fun deletePlaylistEntities(playlistEntities: List<PlaylistEntity>)
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 deletePlaylistSongs(playlists: List<PlaylistEntity>)
suspend fun favoritePlaylist(favorite: String): 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)
@ -45,7 +45,8 @@ class RealRoomRepository(
private val playlistDao: PlaylistDao, private val playlistDao: PlaylistDao,
private val blackListStoreDao: BlackListStoreDao, private val blackListStoreDao: BlackListStoreDao,
private val playCountDao: PlayCountDao, private val playCountDao: PlayCountDao,
private val historyDao: HistoryDao private val historyDao: HistoryDao,
private val lyricsDao: LyricsDao
) : RoomRepository { ) : RoomRepository {
@WorkerThread @WorkerThread
override suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long = override suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long =
@ -66,7 +67,7 @@ class RealRoomRepository(
override suspend fun insertSongs(songs: List<SongEntity>) = override suspend fun insertSongs(songs: List<SongEntity>) =
playlistDao.insertSongsToPlaylist(songs) playlistDao.insertSongsToPlaylist(songs)
override suspend fun getSongs(playlistEntity: PlaylistEntity): List<SongEntity> = override fun getSongs(playlistEntity: PlaylistEntity): LiveData<List<SongEntity>> =
playlistDao.songsFromPlaylist(playlistEntity.playListId) playlistDao.songsFromPlaylist(playlistEntity.playListId)
override suspend fun deletePlaylistEntities(playlistEntities: List<PlaylistEntity>) = override suspend fun deletePlaylistEntities(playlistEntities: List<PlaylistEntity>) =
@ -75,12 +76,15 @@ class RealRoomRepository(
override suspend fun renamePlaylistEntity(playlistId: Int, name: String) = override suspend fun renamePlaylistEntity(playlistId: Int, name: String) =
playlistDao.renamePlaylist(playlistId, name) playlistDao.renamePlaylist(playlistId, name)
override suspend fun deleteSongsInPlaylist(songs: List<SongEntity>) = override suspend fun deleteSongsInPlaylist(songs: List<SongEntity>) {
playlistDao.deleteSongsInPlaylist(songs) songs.forEach {
playlistDao.deleteSongFromPlaylist(it.playlistCreatorId, it.id)
}
}
override suspend fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) = override suspend fun deletePlaylistSongs(playlists: List<PlaylistEntity>) =
playlists.forEach { playlists.forEach {
playlistDao.deleteSongsInPlaylist(it.playListId) playlistDao.deletePlaylistSongs(it.playListId)
} }
override suspend fun favoritePlaylist(favorite: String): PlaylistEntity { override suspend fun favoritePlaylist(favorite: String): PlaylistEntity {
@ -100,7 +104,7 @@ class RealRoomRepository(
) )
override suspend fun removeSongFromPlaylist(songEntity: SongEntity) = override suspend fun removeSongFromPlaylist(songEntity: SongEntity) =
playlistDao.removeSongFromPlaylist(songEntity.playlistCreatorId, songEntity.id) playlistDao.deleteSongFromPlaylist(songEntity.playlistCreatorId, songEntity.id)
override suspend fun addSongToHistory(currentSong: Song) = override suspend fun addSongToHistory(currentSong: Song) =
historyDao.insertSongInHistory(currentSong.toHistoryEntity(System.currentTimeMillis())) historyDao.insertSongInHistory(currentSong.toHistoryEntity(System.currentTimeMillis()))

View file

@ -35,7 +35,6 @@ object PreferenceUtil {
CategoryInfo(CategoryInfo.Category.Artists, true), CategoryInfo(CategoryInfo.Category.Artists, true),
CategoryInfo(CategoryInfo.Category.Playlists, true), CategoryInfo(CategoryInfo.Category.Playlists, true),
CategoryInfo(CategoryInfo.Category.Genres, false), CategoryInfo(CategoryInfo.Category.Genres, false),
CategoryInfo(CategoryInfo.Category.Queue, false),
CategoryInfo(CategoryInfo.Category.Folder, false) CategoryInfo(CategoryInfo.Category.Folder, false)
) )

View file

@ -4,15 +4,33 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="16dp"> android:background="?attr/colorSurface"
android:padding="8dp">
<ScrollView <com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent" android:id="@+id/dialogTitle"
android:layout_height="match_parent" android:layout_width="0dp"
app:layout_constraintBottom_toBottomOf="parent" android:layout_height="wrap_content"
android:padding="16dp"
android:textAppearance="@style/TextViewHeadline6"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" />
<ScrollView
android:layout_width="0dp"
android:layout_height="0dp"
android:paddingHorizontal="16dp"
app:layout_constraintBottom_toTopOf="@id/syncedLyrics"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/dialogTitle">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/lyricsText" android:id="@+id/lyricsText"
@ -20,14 +38,23 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="@style/TextViewBody1" android:textAppearance="@style/TextViewBody1"
tools:text="@tools:sample/lorem/random" /> tools:text="@tools:sample/lorem/random" />
</ScrollView>
<ProgressBar <ProgressBar
android:id="@+id/progressBar" android:id="@+id/progressBar"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="16dp" />
</FrameLayout>
</ScrollView>
<com.google.android.material.button.MaterialButton
android:id="@+id/syncedLyrics"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/synced_lyrics"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -30,11 +30,6 @@
android:name="code.name.monkey.retromusic.fragments.playlists.PlaylistsFragment" android:name="code.name.monkey.retromusic.fragments.playlists.PlaylistsFragment"
tools:layout="@layout/fragment_main_activity_recycler_view" /> tools:layout="@layout/fragment_main_activity_recycler_view" />
<fragment
android:id="@+id/action_playing_queue"
android:name="code.name.monkey.retromusic.fragments.queue.PlayingQueueFragment"
tools:layout="@layout/fragment_main_activity_recycler_view" />
<fragment <fragment
android:id="@+id/action_folder" android:id="@+id/action_folder"
android:name="code.name.monkey.retromusic.fragments.folder.FoldersFragment" android:name="code.name.monkey.retromusic.fragments.folder.FoldersFragment"

View file

@ -53,6 +53,7 @@ object VersionUtils {
/** /**
* @return true if device is running API >= 28 * @return true if device is running API >= 28
*/ */
@JvmStatic
fun hasQ(): Boolean { fun hasQ(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
} }

View file

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.3.72' ext.kotlin_version = '1.4.10'
repositories { repositories {
jcenter() jcenter()
google() google()