Code refactor

main
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'
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-android:$kotlin_coroutines_version"
@ -171,6 +171,6 @@ dependencies {
implementation 'org.jsoup:jsoup:1.11.1'
implementation 'me.zhanghai.android.fastscroll:library:1.1.0'
implementation 'me.jorgecastillo:androidcolorx:0.2.0'
implementation 'org.jsoup:jsoup:1.11.1'
debugImplementation 'com.amitshekhar.android:debug-db:1.0.6'
}

View File

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

View File

@ -92,7 +92,7 @@ class AlbumCoverPagerAdapter(
albumCover = view.findViewById(R.id.player_image)
albumCover.setOnClickListener {
LyricsDialog().show(childFragmentManager, "LyricsDialog")
//showLyricsDialog()
showLyricsDialog()
}
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>
@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")
suspend fun removeSongFromPlaylist(playlistId: Int, songId: Int)
suspend fun deleteSongFromPlaylist(playlistId: Int, songId: Int)
@Transaction
@Query("SELECT * FROM PlaylistEntity")
@ -34,7 +34,7 @@ interface PlaylistDao {
suspend fun isSongExistsInPlaylist(playlistId: Int, songId: Int): List<SongEntity>
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistId")
suspend fun songsFromPlaylist(playlistId: Int): List<SongEntity>
fun songsFromPlaylist(playlistId: Int): LiveData<List<SongEntity>>
@Delete
suspend fun deletePlaylist(playlistEntity: PlaylistEntity)
@ -43,7 +43,7 @@ interface PlaylistDao {
suspend fun deletePlaylists(playlistEntities: List<PlaylistEntity>)
@Delete
suspend fun deleteSongsInPlaylist(songs: List<SongEntity>)
suspend fun deletePlaylistSongs(songs: List<SongEntity>)
@Query("SELECT * FROM SongEntity WHERE playlist_creator_id= :playlistId")
@ -53,5 +53,4 @@ interface PlaylistDao {
fun favoritesSongs(playlistId: Int): List<SongEntity>
}

View File

@ -4,8 +4,8 @@ import androidx.room.Database
import androidx.room.RoomDatabase
@Database(
entities = [PlaylistEntity::class, SongEntity::class, HistoryEntity::class, PlayCountEntity::class, BlackListStoreEntity::class],
version = 20,
entities = [PlaylistEntity::class, SongEntity::class, HistoryEntity::class, PlayCountEntity::class, BlackListStoreEntity::class, LyricsEntity::class],
version = 21,
exportSchema = false
)
abstract class RetroDatabase : RoomDatabase() {
@ -13,4 +13,5 @@ abstract class RetroDatabase : RoomDatabase() {
abstract fun blackListStore(): BlackListStoreDao
abstract fun playCountDao(): PlayCountDao
abstract fun historyDao(): HistoryDao
abstract fun lyricsDao(): LyricsDao
}

View File

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

View File

@ -7,6 +7,8 @@ import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
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.network.Result
import code.name.monkey.retromusic.repository.Repository
@ -34,16 +36,23 @@ class LyricsDialog : DialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val song = MusicPlayerRemote.currentSong
dialogTitle.text = song.title
syncedLyrics.accentTextColor()
lifecycleScope.launch(IO) {
val result: Result<String> = repository.lyrics(
MusicPlayerRemote.currentSong.artistName,
MusicPlayerRemote.currentSong.title
song.artistName,
song.title
)
withContext(Main) {
when (result) {
is Result.Error -> println("Error")
is Result.Error -> progressBar.hide()
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.CheckBox
import android.widget.SeekBar
import androidx.annotation.*
import androidx.appcompat.content.res.AppCompatResources
import androidx.annotation.AttrRes
import androidx.annotation.CheckResult
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat
@ -97,6 +99,10 @@ fun Button.accentTextColor() {
setTextColor(ThemeStore.accentColor(App.getContext()))
}
fun MaterialButton.accentTextColor() {
setTextColor(ThemeStore.accentColor(App.getContext()))
}
fun SeekBar.applyColor(@ColorInt color: Int) {
thumbTintList = ColorStateList.valueOf(color)
progressTintList = ColorStateList.valueOf(color)

View File

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

View File

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

View File

@ -3,16 +3,11 @@ package code.name.monkey.retromusic.fragments.playlists
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.db.toSongs
import code.name.monkey.retromusic.db.SongEntity
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
import code.name.monkey.retromusic.model.Song
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(
private val realRepository: RealRepository,
@ -26,17 +21,8 @@ class PlaylistDetailsViewModel(
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() {
/*if (playlist !is AbsCustomPlaylist) {
@ -65,4 +51,4 @@ class PlaylistDetailsViewModel(
override fun onPlayStateChanged() {}
override fun onRepeatModeChanged() {}
override fun onShuffleModeChanged() {}
}
}

View File

@ -63,9 +63,8 @@ public class CategoryInfo implements Parcelable {
Songs(R.id.action_song, R.string.songs, R.drawable.ic_audiotrack),
Albums(R.id.action_album, R.string.albums, R.drawable.ic_album),
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),
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);
public final int icon;

View File

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

View File

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

View File

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

View File

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

View File

@ -4,30 +4,57 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
android:background="?attr/colorSurface"
android:padding="8dp">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/dialogTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="16dp"
android:textAppearance="@style/TextViewHeadline6"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
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_toTopOf="parent">
app:layout_constraintTop_toBottomOf="@id/dialogTitle">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/lyricsText"
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextViewBody1"
tools:text="@tools:sample/lorem/random" />
android:layout_height="wrap_content">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/lyricsText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextViewBody1"
tools:text="@tools:sample/lorem/random" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="16dp" />
</FrameLayout>
</ScrollView>
<ProgressBar
android:id="@+id/progressBar"
<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_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -30,11 +30,6 @@
android:name="code.name.monkey.retromusic.fragments.playlists.PlaylistsFragment"
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
android:id="@+id/action_folder"
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
*/
@JvmStatic
fun hasQ(): Boolean {
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.
buildscript {
ext.kotlin_version = '1.3.72'
ext.kotlin_version = '1.4.10'
repositories {
jcenter()
google()