Code refactor
This commit is contained in:
parent
5ebeb9c587
commit
0ef83c7136
23 changed files with 156 additions and 94 deletions
|
@ -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'
|
||||||
}
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
||||||
|
)
|
|
@ -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>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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
|
||||||
}
|
}
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>()
|
||||||
}
|
}
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()))
|
||||||
|
|
|
@ -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)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in a new issue