This commit is contained in:
vfsfitvnm
2022-07-18 13:29:44 +02:00
parent 06b4fcdc63
commit 61eeeb07c0
13 changed files with 1355 additions and 55 deletions

View File

@@ -368,7 +368,7 @@ fun MediaItemMenu(
)
}
onSetSleepTimer?.let { onSetSleepTimer ->
onSetSleepTimer?.let {
val binder = LocalPlayerServiceBinder.current
val (colorPalette, typography) = LocalAppearance.current

View File

@@ -28,8 +28,13 @@ import it.vfsfitvnm.vimusic.enums.BuiltInPlaylist
import it.vfsfitvnm.vimusic.models.DetailedSong
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.components.themed.*
import it.vfsfitvnm.vimusic.ui.styling.*
import it.vfsfitvnm.vimusic.ui.components.themed.InFavoritesMediaItemMenu
import it.vfsfitvnm.vimusic.ui.components.themed.Menu
import it.vfsfitvnm.vimusic.ui.components.themed.MenuEntry
import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu
import it.vfsfitvnm.vimusic.ui.styling.Dimensions
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.ui.styling.px
import it.vfsfitvnm.vimusic.ui.views.SongItem
import it.vfsfitvnm.vimusic.utils.*
import kotlinx.coroutines.Dispatchers
@@ -70,10 +75,10 @@ fun BuiltInPlaylistScreen(
val songs by remember(binder?.cache, builtInPlaylist) {
when (builtInPlaylist) {
BuiltInPlaylist.Favorites -> Database.favorites()
BuiltInPlaylist.Cached -> Database.songsByRowIdDesc().map { songs ->
BuiltInPlaylist.Cached -> Database.songsWithContentLength().map { songs ->
songs.filter { song ->
song.song.contentLength?.let { contentLength ->
binder?.cache?.isCached(song.song.id, 0, contentLength)
song.contentLength?.let {
binder?.cache?.isCached(song.song.id, 0, song.contentLength)
} ?: false
}
}

View File

@@ -13,10 +13,12 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicText
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
@@ -43,6 +45,7 @@ import it.vfsfitvnm.vimusic.Database
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
import it.vfsfitvnm.vimusic.models.Format
import it.vfsfitvnm.vimusic.models.Song
import it.vfsfitvnm.vimusic.query
import it.vfsfitvnm.vimusic.ui.components.*
@@ -50,8 +53,10 @@ import it.vfsfitvnm.vimusic.ui.components.themed.BaseMediaItemMenu
import it.vfsfitvnm.vimusic.ui.components.themed.LoadingOrError
import it.vfsfitvnm.vimusic.ui.styling.*
import it.vfsfitvnm.vimusic.utils.*
import it.vfsfitvnm.youtubemusic.YouTube
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.runBlocking
import kotlin.math.roundToInt
@@ -186,7 +191,6 @@ fun PlayerView(
) {
Thumbnail(
playerState = playerState,
song = song,
modifier = Modifier
)
}
@@ -217,7 +221,6 @@ fun PlayerView(
) {
Thumbnail(
playerState = playerState,
song = song,
modifier = Modifier
)
}
@@ -314,7 +317,6 @@ fun PlayerView(
@Composable
private fun Thumbnail(
playerState: PlayerState,
song: Song?,
modifier: Modifier = Modifier
) {
val (_, typography) = LocalAppearance.current
@@ -378,25 +380,17 @@ private fun Thumbnail(
enter = fadeIn(),
exit = fadeOut(),
) {
var cachedBytes by remember(song?.id) {
mutableStateOf(binder.cache.getCachedBytes(playerState.mediaItem.mediaId, 0, -1))
val key = playerState.mediaItem.mediaId
var cachedBytes by remember(key) {
mutableStateOf(binder.cache.getCachedBytes(key, 0, -1))
}
val loudnessDb by remember {
derivedStateOf {
song?.loudnessDb ?: playerState.mediaMetadata.extras?.getFloatOrNull("loudnessDb")
}
}
val contentLength by remember {
derivedStateOf {
song?.contentLength ?: playerState.mediaMetadata.extras?.getLongOrNull("contentLength")
}
}
DisposableEffect(song?.id) {
val key = playerState.mediaItem.mediaId
val format by remember(key) {
Database.format(key)
}.collectAsState(initial = null, context = Dispatchers.IO)
DisposableEffect(key) {
val listener = object : Cache.Listener {
override fun onSpanAdded(cache: Cache, span: CacheSpan) {
cachedBytes += span.length
@@ -451,6 +445,10 @@ private fun Thumbnail(
text = "Loudness",
style = typography.xs.semiBold.color(BlackColorPalette.text)
)
BasicText(
text = "Bitrate",
style = typography.xs.semiBold.color(BlackColorPalette.text)
)
BasicText(
text = "Size",
style = typography.xs.semiBold.color(BlackColorPalette.text)
@@ -471,13 +469,19 @@ private fun Thumbnail(
style = typography.xs.semiBold.color(BlackColorPalette.text)
)
BasicText(
text = loudnessDb?.let { loudnessDb ->
text = format?.loudnessDb?.let { loudnessDb ->
"%.2f dB".format(loudnessDb)
} ?: "Unknown",
style = typography.xs.semiBold.color(BlackColorPalette.text)
)
BasicText(
text = contentLength?.let { contentLength ->
text = format?.bitrate?.let { bitrate ->
"${bitrate / 1000} kbps"
} ?: "Unknown",
style = typography.xs.semiBold.color(BlackColorPalette.text)
)
BasicText(
text = format?.contentLength?.let { contentLength ->
Formatter.formatShortFileSize(
context,
contentLength
@@ -489,7 +493,7 @@ private fun Thumbnail(
text = buildString {
append(Formatter.formatShortFileSize(context, cachedBytes))
contentLength?.let { contentLength ->
format?.contentLength?.let { contentLength ->
append(" (${(cachedBytes.toFloat() / contentLength * 100).roundToInt()}%)")
}
},
@@ -497,6 +501,41 @@ private fun Thumbnail(
)
}
}
if (format != null && format?.itag == null) {
BasicText(
text = "FETCH MISSING DATA",
style = typography.xxs.semiBold.color(BlackColorPalette.text),
modifier = Modifier
.clickable(
indication = rememberRipple(bounded = true),
interactionSource = remember { MutableInteractionSource() },
onClick = {
query {
runBlocking(Dispatchers.IO) {
YouTube.player(key)?.map { response ->
response.streamingData?.adaptiveFormats?.findLast { format ->
format.itag == 251 || format.itag == 140
}?.let { format ->
Format(
songId = key,
itag = format.itag,
mimeType = format.mimeType,
bitrate = format.bitrate,
loudnessDb = response.playerConfig?.audioConfig?.loudnessDb?.toFloat(),
contentLength = format.contentLength,
lastModified = format.lastModified
)
}
}
}?.getOrNull()?.let(Database::insert)
}
}
)
.padding(all = 16.dp)
.align(Alignment.End)
)
}
}
}
}