WIP lyric selection

This commit is contained in:
Damontecres 2026-02-28 20:38:32 -05:00
parent 6fa3f550b0
commit d37c7604d2
No known key found for this signature in database
3 changed files with 49 additions and 24 deletions

View file

@ -22,7 +22,6 @@ import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.tv.material3.Text
import com.github.damontecres.wholphin.R
import com.github.damontecres.wholphin.data.model.CollectionFolderFilter
import com.github.damontecres.wholphin.data.model.GetItemsFilter
@ -55,7 +54,6 @@ fun CollectionFolderMusic(
stringResource(R.string.recommended),
stringResource(R.string.albums),
stringResource(R.string.artists),
stringResource(R.string.playlists),
stringResource(R.string.genres),
stringResource(R.string.songs),
)
@ -173,14 +171,8 @@ fun CollectionFolderMusic(
)
}
// Playlists
3 -> {
// TODO
Text("TODO")
}
// Genres
4 -> {
3 -> {
GenreCardGrid(
itemId = destination.itemId,
includeItemTypes = listOf(BaseItemKind.MUSIC_ALBUM, BaseItemKind.AUDIO),
@ -192,7 +184,7 @@ fun CollectionFolderMusic(
}
// Songs
5 -> {
4 -> {
CollectionFolderGrid(
preferences = preferences,
onClickItem = { _, item ->

View file

@ -3,20 +3,28 @@ package com.github.damontecres.wholphin.ui.detail.music
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.relocation.BringIntoViewRequester
import androidx.compose.foundation.relocation.bringIntoViewRequester
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.Text
@ -26,6 +34,7 @@ import org.jellyfin.sdk.model.api.LyricLine
@Composable
fun LyricsContent(
synced: Boolean,
lyrics: LyricDto?,
currentLyricPosition: Int?,
onClick: (LyricLine) -> Unit,
@ -33,16 +42,23 @@ fun LyricsContent(
) {
val listState = rememberLazyListState(currentLyricPosition ?: 0)
val bringIntoViewRequester = remember { BringIntoViewRequester() }
if (synced) {
LaunchedEffect(currentLyricPosition) {
if (currentLyricPosition != null) {
listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index?.let {
if (currentLyricPosition !in 0..it) {
listState.animateScrollToItem(currentLyricPosition)
}
}
bringIntoViewRequester.bringIntoView()
}
}
}
Column(modifier) {
LazyColumn(
state = listState,
contentPadding = PaddingValues(),
verticalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.fillMaxSize(),
) {
if (lyrics?.lyrics?.isNotEmpty() == true) {
@ -55,13 +71,28 @@ fun LyricsContent(
},
animationSpec = tween(durationMillis = 500, easing = LinearEasing),
)
val interactionSource = remember { MutableInteractionSource() }
val focused by interactionSource.collectIsFocusedAsState()
Box(
modifier =
Modifier
.background(
color = if (focused) MaterialTheme.colorScheme.border.copy(alpha = .66f) else Color.Unspecified,
shape = RoundedCornerShape(8.dp),
),
) {
Text(
text = lyric.text,
style = MaterialTheme.typography.bodyLarge,
color = color,
modifier =
Modifier.ifElse(
Modifier
.padding(4.dp)
.clickable(
enabled = !synced,
onClick = { onClick.invoke(lyric) },
interactionSource = interactionSource,
).ifElse(
index == currentLyricPosition,
Modifier.bringIntoViewRequester(bringIntoViewRequester),
),
@ -70,4 +101,5 @@ fun LyricsContent(
}
}
}
}
}

View file

@ -104,6 +104,7 @@ fun NowPlayingPage(
modifier = Modifier,
) {
LyricsContent(
synced = true,
lyrics = state.lyrics,
currentLyricPosition = state.currentLyricIndex,
onClick = {},