Show empty rows in settings

This commit is contained in:
Damontecres 2026-02-05 14:55:57 -05:00
parent c844395acd
commit c3c054a291
No known key found for this signature in database
3 changed files with 103 additions and 45 deletions

View file

@ -0,0 +1,84 @@
package com.github.damontecres.wholphin.ui.components
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.focusable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.NonRestartableComposable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.Text
/**
* Placeholder for [com.github.damontecres.wholphin.ui.cards.ItemRow]. It is [focusable] so it can be scrolled.
*/
@Composable
@NonRestartableComposable
fun FocusableItemRow(
title: String,
subtitle: String,
modifier: Modifier = Modifier,
isError: Boolean = false,
) = FocusableItemRow(
titleContent = {
Text(
text = title,
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onBackground,
)
},
subtitleContent = {
Text(
text = subtitle,
style = MaterialTheme.typography.titleMedium,
color = if (isError) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.onBackground,
modifier = Modifier.padding(start = 8.dp),
)
},
modifier = modifier,
)
@Composable
fun FocusableItemRow(
titleContent: @Composable () -> Unit,
subtitleContent: @Composable () -> Unit,
modifier: Modifier = Modifier,
) {
val interactionSource = remember { MutableInteractionSource() }
val focused by interactionSource.collectIsFocusedAsState()
val padding by animateDpAsState(if (focused) 8.dp else 0.dp)
val scale by animateFloatAsState(if (focused) 1.1f else 1f)
val background by animateColorAsState(
if (focused) {
MaterialTheme.colorScheme.border.copy(alpha = .25f)
} else {
Color.Unspecified
},
)
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier =
modifier
.padding(start = 8.dp)
.focusable(interactionSource = interactionSource)
.scale(scale)
.background(background, shape = RoundedCornerShape(8.dp))
.padding(padding),
) {
titleContent.invoke()
subtitleContent.invoke()
}
}

View file

@ -1,8 +1,6 @@
package com.github.damontecres.wholphin.ui.main
import androidx.compose.foundation.background
import androidx.compose.foundation.focusGroup
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@ -33,7 +31,6 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.focusRestorer
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
@ -58,6 +55,7 @@ import com.github.damontecres.wholphin.ui.components.DialogParams
import com.github.damontecres.wholphin.ui.components.DialogPopup
import com.github.damontecres.wholphin.ui.components.EpisodeName
import com.github.damontecres.wholphin.ui.components.ErrorMessage
import com.github.damontecres.wholphin.ui.components.FocusableItemRow
import com.github.damontecres.wholphin.ui.components.LoadingPage
import com.github.damontecres.wholphin.ui.components.QuickDetails
import com.github.damontecres.wholphin.ui.data.AddPlaylistViewModel
@ -198,6 +196,7 @@ fun HomePageContent(
loadingState: LoadingState? = null,
listState: LazyListState = rememberLazyListState(),
takeFocus: Boolean = true,
showEmptyRows: Boolean = false,
) {
var position by rememberPosition()
val focusedItem =
@ -264,52 +263,20 @@ fun HomePageContent(
is HomeRowLoadingState.Loading,
is HomeRowLoadingState.Pending,
-> {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
FocusableItemRow(
title = r.title,
subtitle = stringResource(R.string.loading),
modifier = Modifier.animateItem(),
) {
Text(
text = r.title,
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onBackground,
)
Text(
text = stringResource(R.string.loading),
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onBackground,
)
}
}
is HomeRowLoadingState.Error -> {
var focused by remember { mutableStateOf(false) }
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier =
Modifier
.onFocusChanged {
focused = it.isFocused
}.focusable()
.background(
if (focused) {
// Just so the user can tell it has focus
MaterialTheme.colorScheme.border.copy(alpha = .25f)
} else {
Color.Unspecified
},
).animateItem(),
) {
Text(
text = r.title,
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onBackground,
FocusableItemRow(
title = r.title,
subtitle = r.localizedMessage,
isError = true,
modifier = Modifier.animateItem(),
)
Text(
text = r.localizedMessage,
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.error,
)
}
}
is HomeRowLoadingState.Success -> {
@ -369,6 +336,12 @@ fun HomePageContent(
)
},
)
} else if (showEmptyRows) {
FocusableItemRow(
title = r.title,
subtitle = stringResource(R.string.no_results),
modifier = Modifier.animateItem(),
)
}
}
}

View file

@ -256,6 +256,7 @@ fun HomeSettingsPage(
onUpdateBackdrop = viewModel::updateBackdrop,
listState = listState,
takeFocus = false,
showEmptyRows = true,
modifier =
Modifier
.fillMaxHeight()