Save lyrics to the database

This commit is contained in:
vfsfitvnm
2022-06-13 11:25:27 +02:00
parent 13881c2d43
commit 3a6af404ab
5 changed files with 390 additions and 30 deletions

View File

@@ -7,7 +7,6 @@ import androidx.media3.common.MediaItem
import androidx.room.*
import it.vfsfitvnm.vimusic.models.*
import kotlinx.coroutines.flow.Flow
import java.io.ByteArrayOutputStream
@Dao
@@ -125,15 +124,22 @@ interface Database {
@androidx.room.Database(
entities = [
Song::class, SongInPlaylist::class, Playlist::class, Info::class, SongWithAuthors::class, SearchQuery::class, QueuedMediaItem::class
Song::class,
SongInPlaylist::class,
Playlist::class,
Info::class,
SongWithAuthors::class,
SearchQuery::class,
QueuedMediaItem::class
],
views = [
SortedSongInPlaylist::class
],
version = 2,
version = 3,
exportSchema = true,
autoMigrations = [
AutoMigration(from = 1, to = 2)
AutoMigration(from = 1, to = 2),
AutoMigration(from = 2, to = 3),
]
)
@TypeConverters(Converters::class)
@@ -162,7 +168,7 @@ object Converters {
return value?.let { byteArray ->
val parcel = Parcel.obtain()
parcel.unmarshall(byteArray, 0, byteArray.size)
parcel.setDataPosition(0);
parcel.setDataPosition(0)
val pb = parcel.readBundle(MediaItem::class.java.classLoader)
parcel.recycle()

View File

@@ -10,8 +10,9 @@ data class Song(
val albumInfoId: Long?,
val durationText: String,
val thumbnailUrl: String?,
val lyrics: String? = null,
val likedAt: Long? = null,
val totalPlayTimeMs: Long = 0
val totalPlayTimeMs: Long = 0,
) {
val formattedTotalPlayTime: String
get() {

View File

@@ -26,7 +26,9 @@ import it.vfsfitvnm.route.Route
import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.route.empty
import it.vfsfitvnm.route.rememberRoute
import it.vfsfitvnm.vimusic.Database
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.models.Song
import it.vfsfitvnm.vimusic.ui.components.BottomSheet
import it.vfsfitvnm.vimusic.ui.components.BottomSheetState
import it.vfsfitvnm.vimusic.ui.components.Message
@@ -35,10 +37,7 @@ import it.vfsfitvnm.vimusic.ui.components.themed.TextPlaceholder
import it.vfsfitvnm.vimusic.ui.screens.rememberLyricsRoute
import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
import it.vfsfitvnm.vimusic.utils.LocalYoutubePlayer
import it.vfsfitvnm.vimusic.utils.center
import it.vfsfitvnm.vimusic.utils.color
import it.vfsfitvnm.vimusic.utils.medium
import it.vfsfitvnm.vimusic.utils.*
import it.vfsfitvnm.youtubemusic.Outcome
import it.vfsfitvnm.youtubemusic.YouTube
import it.vfsfitvnm.youtubemusic.isEvaluable
@@ -51,6 +50,7 @@ import kotlinx.coroutines.withContext
@Composable
fun PlayerBottomSheet(
layoutState: BottomSheetState,
song: Song?,
onGlobalRouteEmitted: () -> Unit,
modifier: Modifier = Modifier,
) {
@@ -69,10 +69,6 @@ fun PlayerBottomSheet(
mutableStateOf<Outcome<YouTube.NextResult>>(Outcome.Initial)
}
var lyricsOutcome by remember(player.mediaItem!!.mediaId) {
mutableStateOf<Outcome<String?>>(Outcome.Initial)
}
BottomSheet(
state = layoutState,
peekHeight = 128.dp,
@@ -91,7 +87,10 @@ fun PlayerBottomSheet(
Spacer(
modifier = Modifier
.align(Alignment.CenterHorizontally)
.background(color = colorPalette.textDisabled, shape = RoundedCornerShape(16.dp))
.background(
color = colorPalette.textDisabled,
shape = RoundedCornerShape(16.dp)
)
.width(36.dp)
.height(4.dp)
.padding(top = 8.dp)
@@ -175,13 +174,18 @@ fun PlayerBottomSheet(
.background(colorPalette.elevatedBackground)
.fillMaxSize()
) {
var lyricsOutcome by remember(song) {
mutableStateOf(song?.lyrics?.let { Outcome.Success(it) } ?: Outcome.Initial)
}
lyricsRoute {
OutcomeItem(
outcome = lyricsOutcome,
onInitialize = {
lyricsOutcome = Outcome.Loading
println("onInitialize!!")
coroutineScope.launch(Dispatchers.Main) {
lyricsOutcome = Outcome.Loading
if (nextOutcome.isEvaluable) {
nextOutcome = Outcome.Loading
nextOutcome = withContext(Dispatchers.IO) {
@@ -195,6 +199,13 @@ fun PlayerBottomSheet(
lyricsOutcome = nextOutcome.flatMap {
it.lyrics?.text().toNotNull()
}.map {
it ?: ""
}.map {
withContext(Dispatchers.IO) {
Database.update((song ?: Database.insert(player.mediaItem!!)).copy(lyrics = it))
}
it
}
}
},
@@ -205,7 +216,14 @@ fun PlayerBottomSheet(
)
}
) { lyrics ->
if (lyrics != null) {
if (lyrics.isEmpty()) {
Message(
text = "Lyrics not available",
icon = R.drawable.text,
modifier = Modifier
.padding(top = 64.dp)
)
} else {
BasicText(
text = lyrics,
style = typography.xs.center,
@@ -217,13 +235,6 @@ fun PlayerBottomSheet(
.padding(vertical = 16.dp)
.padding(horizontal = 48.dp)
)
} else {
Message(
text = "Lyrics not available",
icon = R.drawable.text,
modifier = Modifier
.padding(top = 64.dp)
)
}
}
}

View File

@@ -68,11 +68,6 @@ fun PlayerView(
size to density.run { size.minus(64.dp).roundToPx() }
}
val song by remember(player.mediaItem?.mediaId) {
player.mediaItem?.mediaId?.let(Database::songFlow)?.distinctUntilChanged() ?: flowOf(null)
}.collectAsState(initial = null, context = Dispatchers.IO)
BottomSheet(
state = layoutState,
modifier = modifier,
@@ -169,6 +164,10 @@ fun PlayerView(
}
}
) {
val song by remember(player.mediaItem?.mediaId) {
player.mediaItem?.mediaId?.let(Database::songFlow)?.distinctUntilChanged() ?: flowOf(null)
}.collectAsState(initial = null, context = Dispatchers.IO)
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
@@ -440,6 +439,7 @@ fun PlayerView(
PlayerBottomSheet(
layoutState = rememberBottomSheetState(64.dp, layoutState.upperBound - 128.dp),
onGlobalRouteEmitted = layoutState.collapse,
song = song,
modifier = Modifier
.padding(bottom = 128.dp)
.align(Alignment.BottomCenter)