From 793f9802e4e8cf5601212adb5096349d1010a3f1 Mon Sep 17 00:00:00 2001 From: damontecres <154766448+damontecres@users.noreply.github.com> Date: Sat, 6 Dec 2025 15:35:17 -0500 Subject: [PATCH] Resize & reshape buttons (#380) Adds a new button implementation which allows for icon buttons to be circular. Overall the buttons are reduced in size. Also, the playback controls are are reduced in size, buttons are smaller and vertical padding is reduced. ![buttons Large](https://github.com/user-attachments/assets/2211d00f-60a7-4a61-be51-a09046fc7433) --- .../damontecres/wholphin/ui/UiConstants.kt | 9 - .../wholphin/ui/components/Button.kt | 173 ++++++++++++++++++ .../wholphin/ui/components/Dialogs.kt | 19 +- .../wholphin/ui/components/ErrorMessage.kt | 10 +- .../wholphin/ui/components/FilterByButton.kt | 69 +++++-- .../wholphin/ui/components/PlayButtons.kt | 141 +++++++++++--- .../wholphin/ui/components/SortByButton.kt | 5 +- .../wholphin/ui/detail/CardGrid.kt | 10 +- .../wholphin/ui/detail/PlaylistList.kt | 2 +- .../ui/detail/livetv/ProgramDialog.kt | 9 +- .../wholphin/ui/playback/PlaybackControls.kt | 40 ++-- .../wholphin/ui/playback/PlaybackOverlay.kt | 123 +++++++------ .../wholphin/ui/playback/PlaybackPage.kt | 13 +- .../ui/preferences/StringInputDialog.kt | 20 +- .../wholphin/ui/setup/InstallUpdatePage.kt | 21 +-- .../damontecres/wholphin/ui/setup/PinEntry.kt | 5 +- .../wholphin/ui/setup/SwitchServerContent.kt | 4 +- .../wholphin/ui/setup/SwitchUserContent.kt | 23 +-- app/src/main/res/values/strings.xml | 2 + 19 files changed, 492 insertions(+), 206 deletions(-) create mode 100644 app/src/main/java/com/github/damontecres/wholphin/ui/components/Button.kt diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt index 39b2048b..5af35e03 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt @@ -1,7 +1,6 @@ package com.github.damontecres.wholphin.ui import android.content.res.Configuration.UI_MODE_TYPE_TELEVISION -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.Font @@ -66,14 +65,6 @@ val SlimItemFields = ItemFields.SORT_NAME, ) -val DefaultButtonPadding = - PaddingValues( - start = 12.dp / 2, - top = 10.dp / 2, - end = 16.dp / 2, - bottom = 10.dp / 2, - ) - object Cards { val height2x3 = 172.dp val playedPercentHeight = 6.dp diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/Button.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/Button.kt new file mode 100644 index 00000000..c65069bd --- /dev/null +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/Button.kt @@ -0,0 +1,173 @@ +// This file was inspired by related Button source files from +// https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-main/tv/tv-material/src/main/java/androidx/tv/material3 + +package com.github.damontecres.wholphin.ui.components + +import androidx.annotation.StringRes +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.NonRestartableComposable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.tv.material3.Border +import androidx.tv.material3.ClickableSurfaceBorder +import androidx.tv.material3.ClickableSurfaceColors +import androidx.tv.material3.ClickableSurfaceDefaults +import androidx.tv.material3.ClickableSurfaceGlow +import androidx.tv.material3.ClickableSurfaceScale +import androidx.tv.material3.ClickableSurfaceShape +import androidx.tv.material3.MaterialTheme +import androidx.tv.material3.ProvideTextStyle +import androidx.tv.material3.Surface +import androidx.tv.material3.Text + +@Composable +fun Button( + onClick: () -> Unit, + modifier: Modifier = Modifier, + onLongClick: (() -> Unit)? = null, + enabled: Boolean = true, + scale: ClickableSurfaceScale = ClickableSurfaceDefaults.scale(), + glow: ClickableSurfaceGlow = ClickableSurfaceDefaults.glow(), + shape: ClickableSurfaceShape = + ClickableSurfaceDefaults.shape( + shape = CircleShape, + ), + colors: ClickableSurfaceColors = + ClickableSurfaceDefaults.colors( + containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.8f), + contentColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f), + focusedContainerColor = MaterialTheme.colorScheme.onSurface, + focusedContentColor = MaterialTheme.colorScheme.inverseOnSurface, + pressedContainerColor = MaterialTheme.colorScheme.onSurface, + pressedContentColor = MaterialTheme.colorScheme.inverseOnSurface, + disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f), + disabledContentColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f), + ), + tonalElevation: Dp = 0.dp, + border: ClickableSurfaceBorder = + ClickableSurfaceDefaults.border( + border = Border.None, + focusedBorder = Border.None, + pressedBorder = Border.None, + disabledBorder = Border.None, + focusedDisabledBorder = + Border( + border = + BorderStroke( + width = 1.5.dp, + color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.2f), + ), + shape = CircleShape, + ), + ), + contentPadding: PaddingValues = DefaultButtonPadding, + contentHeight: Dp = MinButtonSize, + interactionSource: MutableInteractionSource? = null, + content: @Composable RowScope.() -> Unit, +) { + Surface( + modifier = modifier.semantics { role = Role.Button }, + onClick = onClick, + onLongClick = onLongClick, + enabled = enabled, + scale = scale, + glow = glow, + shape = shape, + colors = colors, + tonalElevation = tonalElevation, + border = border, + interactionSource = interactionSource, + ) { + ProvideTextStyle(value = MaterialTheme.typography.labelLarge) { + Row( + modifier = + Modifier + .padding(contentPadding) + .height(contentHeight), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + content = content, + ) + } + } +} + +@Composable +@NonRestartableComposable +fun TextButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + onLongClick: (() -> Unit)? = null, + enabled: Boolean = true, + contentPadding: PaddingValues = + PaddingValues( + start = 8.dp, + top = 4.dp, + end = 8.dp, + bottom = 4.dp, + ), + contentHeight: Dp = 32.dp, + interactionSource: MutableInteractionSource? = null, + content: @Composable RowScope.() -> Unit, +) = Button( + onClick = onClick, + modifier = modifier, + onLongClick = onLongClick, + enabled = enabled, + contentPadding = contentPadding, + contentHeight = contentHeight, + interactionSource = interactionSource, + content = content, +) + +@Composable +fun TextButton( + @StringRes stringRes: Int, + onClick: () -> Unit, + modifier: Modifier = Modifier, + onLongClick: (() -> Unit)? = null, + enabled: Boolean = true, + contentPadding: PaddingValues = + PaddingValues( + start = 8.dp, + top = 4.dp, + end = 8.dp, + bottom = 4.dp, + ), + contentHeight: Dp = 32.dp, + interactionSource: MutableInteractionSource? = null, +) = Button( + onClick = onClick, + modifier = modifier, + onLongClick = onLongClick, + enabled = enabled, + contentPadding = contentPadding, + contentHeight = contentHeight, + interactionSource = interactionSource, + content = { + Text(text = stringResource(stringRes)) + }, +) + +val DefaultButtonPadding = + PaddingValues( + start = 4.dp, + top = 4.dp, + end = 4.dp, + bottom = 4.dp, + ) diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/Dialogs.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/Dialogs.kt index b2363059..e6af6443 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/Dialogs.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/Dialogs.kt @@ -45,7 +45,6 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties -import androidx.tv.material3.Button import androidx.tv.material3.Icon import androidx.tv.material3.ListItem import androidx.tv.material3.LocalContentColor @@ -443,20 +442,14 @@ fun ConfirmDialogContent( horizontalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.fillMaxWidth(), ) { - Button( + TextButton( + stringRes = R.string.cancel, onClick = onCancel, - ) { - Text( - text = stringResource(R.string.cancel), - ) - } - Button( + ) + TextButton( + stringRes = R.string.confirm, onClick = onConfirm, - ) { - Text( - text = stringResource(R.string.confirm), - ) - } + ) } } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/ErrorMessage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/ErrorMessage.kt index f833e228..76c9e097 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/ErrorMessage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/ErrorMessage.kt @@ -10,7 +10,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.ViewModel -import androidx.tv.material3.Button import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import com.github.damontecres.wholphin.R @@ -56,15 +55,12 @@ fun ErrorMessage( color = MaterialTheme.colorScheme.error, style = MaterialTheme.typography.titleMedium, ) - Button( + TextButton( + stringRes = R.string.send_app_logs, onClick = { viewModel.sendLogs() }, - ) { - Text( - text = stringResource(R.string.send_app_logs), - ) - } + ) message?.let { Text( text = it, diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/FilterByButton.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/FilterByButton.kt index b6dd6474..7f8553ac 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/FilterByButton.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/FilterByButton.kt @@ -4,9 +4,13 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsFocusedAsState import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredSizeIn import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.widthIn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Delete @@ -18,17 +22,16 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.tv.material3.Button import androidx.tv.material3.Icon import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text @@ -46,8 +49,9 @@ import com.github.damontecres.wholphin.data.filter.PlayedFilter import com.github.damontecres.wholphin.data.filter.VideoTypeFilter import com.github.damontecres.wholphin.data.filter.YearFilter import com.github.damontecres.wholphin.data.model.GetItemsFilter -import com.github.damontecres.wholphin.ui.DefaultButtonPadding import com.github.damontecres.wholphin.ui.FontAwesome +import com.github.damontecres.wholphin.ui.PreviewTvSpec +import com.github.damontecres.wholphin.ui.theme.WholphinTheme import com.github.damontecres.wholphin.ui.tryRequestFocus import java.util.UUID @@ -353,35 +357,64 @@ fun ExpandableFilterButton( interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, iconColor: Color = Color.Unspecified, ) { - val resources = LocalResources.current val isFocused = interactionSource.collectIsFocusedAsState().value Button( onClick = onClick, - modifier = modifier.heightIn(min = 40.dp), - contentPadding = DefaultButtonPadding, + modifier = + modifier.requiredSizeIn( + minWidth = MinButtonSize, + minHeight = MinButtonSize, + maxHeight = MinButtonSize, + ), + contentPadding = PaddingValues(0.dp), // DefaultButtonPadding, interactionSource = interactionSource, ) { - Text( - text = stringResource(R.string.fa_filter), - style = MaterialTheme.typography.titleSmall, - color = iconColor, - fontSize = 16.sp, - fontFamily = FontAwesome, - textAlign = TextAlign.Center, - modifier = Modifier, - ) + Box( + modifier = + Modifier + .fillMaxHeight() + .widthIn(min = if (filterCount > 0 || isFocused) (MinButtonSize - 12.dp) else MinButtonSize), + ) { + Text( + text = stringResource(R.string.fa_filter), + style = MaterialTheme.typography.titleSmall, + color = iconColor, + fontSize = 16.sp, + fontFamily = FontAwesome, + textAlign = TextAlign.Center, + modifier = Modifier.align(Alignment.Center), + ) + } AnimatedVisibility(filterCount > 0) { Text( text = filterCount.toString(), style = MaterialTheme.typography.titleSmall, - modifier = Modifier.padding(start = 4.dp), + modifier = Modifier.padding(end = 4.dp), ) } AnimatedVisibility(isFocused) { Text( text = stringResource(R.string.filter), style = MaterialTheme.typography.titleSmall, - modifier = Modifier.padding(start = 4.dp), + modifier = Modifier.padding(start = 4.dp, end = 4.dp), + ) + } + } +} + +@PreviewTvSpec +@Composable +private fun ExpandableFilterButtonPreview() { + WholphinTheme { + Column { + ExpandableFilterButton( + filterCount = 2, + onClick = {}, + ) + + ExpandableFilterButton( + filterCount = 0, + onClick = {}, ) } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/PlayButtons.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/PlayButtons.kt index 6790e627..6a14fdbf 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/PlayButtons.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/PlayButtons.kt @@ -6,10 +6,14 @@ import androidx.compose.foundation.focusGroup 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.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredSizeIn import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyRow import androidx.compose.material.icons.Icons @@ -18,6 +22,7 @@ import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.Refresh import androidx.compose.runtime.Composable import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusState @@ -31,16 +36,18 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.tv.material3.Button import androidx.tv.material3.Icon import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import com.github.damontecres.wholphin.R -import com.github.damontecres.wholphin.ui.DefaultButtonPadding import com.github.damontecres.wholphin.ui.FontAwesome import com.github.damontecres.wholphin.ui.PreviewTvSpec +import com.github.damontecres.wholphin.ui.data.SortAndDirection import com.github.damontecres.wholphin.ui.ifElse +import com.github.damontecres.wholphin.ui.theme.PreviewInteractionSource import com.github.damontecres.wholphin.ui.theme.WholphinTheme +import org.jellyfin.sdk.model.api.ItemSortBy +import org.jellyfin.sdk.model.api.SortOrder import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds @@ -77,7 +84,8 @@ fun ExpandablePlayButtons( playOnClick, Modifier .onFocusChanged(buttonOnFocusChanged) - .focusRequester(firstFocus), + .focusRequester(firstFocus) + .animateItem(), ) } item("restart") { @@ -86,7 +94,9 @@ fun ExpandablePlayButtons( Duration.ZERO, Icons.Default.Refresh, playOnClick, - Modifier.onFocusChanged(buttonOnFocusChanged), + Modifier + .onFocusChanged(buttonOnFocusChanged) + .animateItem(), mirrorIcon = true, ) } @@ -99,7 +109,8 @@ fun ExpandablePlayButtons( playOnClick, Modifier .onFocusChanged(buttonOnFocusChanged) - .focusRequester(firstFocus), + .focusRequester(firstFocus) + .animateItem(), ) } } @@ -110,7 +121,10 @@ fun ExpandablePlayButtons( title = if (watched) R.string.mark_unwatched else R.string.mark_watched, iconStringRes = if (watched) R.string.fa_eye else R.string.fa_eye_slash, onClick = watchOnClick, - modifier = Modifier.onFocusChanged(buttonOnFocusChanged), + modifier = + Modifier + .onFocusChanged(buttonOnFocusChanged) + .animateItem(), ) } @@ -121,7 +135,10 @@ fun ExpandablePlayButtons( iconStringRes = R.string.fa_heart, onClick = favoriteOnClick, iconColor = if (favorite) Color.Red else Color.Unspecified, - modifier = Modifier.onFocusChanged(buttonOnFocusChanged), + modifier = + Modifier + .onFocusChanged(buttonOnFocusChanged) + .animateItem(), ) } @@ -132,12 +149,16 @@ fun ExpandablePlayButtons( Duration.ZERO, Icons.Default.MoreVert, { moreOnClick.invoke() }, - Modifier.onFocusChanged(buttonOnFocusChanged), + Modifier + .onFocusChanged(buttonOnFocusChanged) + .animateItem(), ) } } } +val MinButtonSize = 40.dp + /** * An icon button typically used in a row for playing media * @@ -156,20 +177,36 @@ fun ExpandablePlayButton( val isFocused = interactionSource.collectIsFocusedAsState().value Button( onClick = { onClick.invoke(resume) }, - modifier = modifier, + modifier = + modifier.requiredSizeIn( + minWidth = MinButtonSize, + minHeight = MinButtonSize, + maxHeight = MinButtonSize, + ), contentPadding = DefaultButtonPadding, interactionSource = interactionSource, ) { - Icon( - imageVector = icon, - contentDescription = null, - modifier = Modifier.ifElse(mirrorIcon, Modifier.graphicsLayer { scaleX = -1f }), - ) + Box( + modifier = + Modifier + .padding(start = 2.dp, top = 2.dp) + .height(MinButtonSize), + ) { + Icon( + imageVector = icon, + contentDescription = null, + modifier = + Modifier + .size(28.dp) + .ifElse(mirrorIcon, Modifier.graphicsLayer { scaleX = -1f }), + ) + } AnimatedVisibility(isFocused) { Spacer(Modifier.size(8.dp)) Text( text = stringResource(title), style = MaterialTheme.typography.titleSmall, + modifier = Modifier.padding(end = 4.dp), ) } } @@ -190,24 +227,35 @@ fun ExpandableFaButton( val isFocused = interactionSource.collectIsFocusedAsState().value Button( onClick = onClick, - modifier = modifier.heightIn(min = 40.dp), + modifier = + modifier.requiredSizeIn( + minWidth = MinButtonSize, + minHeight = MinButtonSize, + maxHeight = MinButtonSize, + ), contentPadding = DefaultButtonPadding, interactionSource = interactionSource, ) { - Text( - text = stringResource(iconStringRes), - style = MaterialTheme.typography.titleSmall, - color = iconColor, - fontSize = 16.sp, - fontFamily = FontAwesome, - textAlign = TextAlign.Center, - modifier = Modifier, - ) + Box( + modifier = + Modifier + .size(32.dp), + ) { + Text( + text = stringResource(iconStringRes), + style = MaterialTheme.typography.titleSmall, + color = iconColor, + fontSize = 16.sp, + fontFamily = FontAwesome, + textAlign = TextAlign.Center, + modifier = Modifier.align(Alignment.Center), + ) + } AnimatedVisibility(isFocused) { Text( text = stringResource(title), style = MaterialTheme.typography.titleSmall, - modifier = Modifier.padding(start = 4.dp), + modifier = Modifier.padding(end = 4.dp), ) } } @@ -230,3 +278,44 @@ private fun ExpandablePlayButtonsPreview() { ) } } + +@PreviewTvSpec +@Composable +private fun ViewOptionsPreview() { + val source = remember { PreviewInteractionSource() } + WholphinTheme { + Column( + verticalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier.padding(16.dp), + ) { + ExpandablePlayButton( + title = R.string.play, + resume = Duration.ZERO, + icon = Icons.Default.PlayArrow, + onClick = {}, + interactionSource = source, + ) + ExpandableFaButton( + title = R.string.play, + iconStringRes = R.string.fa_eye, + onClick = {}, + modifier = Modifier, + interactionSource = source, + ) + + Row { + ExpandableFaButton( + title = R.string.mark_unwatched, + iconStringRes = R.string.fa_eye, + onClick = {}, + modifier = Modifier, + ) + SortByButton( + sortOptions = listOf(), + current = SortAndDirection(ItemSortBy.DEFAULT, SortOrder.ASCENDING), + onSortChange = {}, + ) + } + } + } +} diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/SortByButton.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/SortByButton.kt index d63842c1..405e0fb6 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/SortByButton.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/SortByButton.kt @@ -13,13 +13,14 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.withStyle -import androidx.tv.material3.Button import androidx.tv.material3.Text import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.ui.FontAwesome +import com.github.damontecres.wholphin.ui.PreviewTvSpec import com.github.damontecres.wholphin.ui.data.SortAndDirection import com.github.damontecres.wholphin.ui.data.flip import com.github.damontecres.wholphin.ui.data.getStringRes +import com.github.damontecres.wholphin.ui.theme.WholphinTheme import org.jellyfin.sdk.model.api.ItemSortBy import org.jellyfin.sdk.model.api.SortOrder @@ -42,7 +43,7 @@ fun SortByButton( val context = LocalContext.current Box(modifier = modifier) { - Button( + TextButton( onClick = { sortByDropDown = true }, onLongClick = { onSortChange.invoke(current.flip()) diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CardGrid.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CardGrid.kt index b83ee031..633ba5bc 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CardGrid.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CardGrid.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -45,9 +46,9 @@ import androidx.compose.ui.input.key.type import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import androidx.tv.material3.Button import androidx.tv.material3.LocalContentColor import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text @@ -56,6 +57,8 @@ import com.github.damontecres.wholphin.data.model.BaseItem import com.github.damontecres.wholphin.ui.AppColors import com.github.damontecres.wholphin.ui.FontAwesome import com.github.damontecres.wholphin.ui.cards.GridCard +import com.github.damontecres.wholphin.ui.components.Button +import com.github.damontecres.wholphin.ui.components.TextButton import com.github.damontecres.wholphin.ui.ifElse import com.github.damontecres.wholphin.ui.playback.isBackwardButton import com.github.damontecres.wholphin.ui.playback.isForwardButton @@ -438,6 +441,7 @@ fun AlphabetButtons( } val focusRequesters = remember { List(letters.length) { FocusRequester() } } LazyColumn( + contentPadding = PaddingValues(4.dp), state = listState, modifier = modifier.focusProperties { @@ -452,7 +456,7 @@ fun AlphabetButtons( ) { index -> val interactionSource = remember { MutableInteractionSource() } val focused by interactionSource.collectIsFocusedAsState() - Button( + TextButton( modifier = Modifier .size(24.dp) @@ -472,6 +476,8 @@ fun AlphabetButtons( Text( text = letters[index].toString(), color = color, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth(), ) } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/PlaylistList.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/PlaylistList.kt index 8bea4a89..b68d425e 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/PlaylistList.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/PlaylistList.kt @@ -38,7 +38,6 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties -import androidx.tv.material3.Button import androidx.tv.material3.Icon import androidx.tv.material3.ListItem import androidx.tv.material3.MaterialTheme @@ -47,6 +46,7 @@ import androidx.tv.material3.surfaceColorAtElevation import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.data.model.PlaylistInfo import com.github.damontecres.wholphin.ui.components.BasicDialog +import com.github.damontecres.wholphin.ui.components.Button import com.github.damontecres.wholphin.ui.components.EditTextBox import com.github.damontecres.wholphin.ui.components.ErrorMessage import com.github.damontecres.wholphin.ui.isNotNullOrBlank diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/ProgramDialog.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/ProgramDialog.kt index 9f1d5215..54ebf864 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/ProgramDialog.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/livetv/ProgramDialog.kt @@ -28,15 +28,16 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog -import androidx.tv.material3.Button import androidx.tv.material3.Icon import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import androidx.tv.material3.surfaceColorAtElevation import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.data.model.BaseItem +import com.github.damontecres.wholphin.ui.components.Button import com.github.damontecres.wholphin.ui.components.CircularProgress import com.github.damontecres.wholphin.ui.components.ErrorMessage +import com.github.damontecres.wholphin.ui.components.TextButton import com.github.damontecres.wholphin.ui.ifElse import com.github.damontecres.wholphin.ui.isNotNullOrBlank import com.github.damontecres.wholphin.ui.seasonEpisode @@ -145,7 +146,7 @@ fun ProgramDialog( .fillMaxWidth(), ) { if (now.isAfter(dto.startDate!!) && now.isBefore(dto.endDate!!)) { - Button( + TextButton( onClick = onWatch, modifier = Modifier, ) { @@ -179,7 +180,7 @@ fun ProgramDialog( ) { if (dto.isSeries ?: false) { item { - Button( + TextButton( onClick = { if (isSeriesRecording) { onCancelRecord.invoke(true) @@ -221,7 +222,7 @@ fun ProgramDialog( if (dto.endDate?.isAfter(LocalDateTime.now()) ?: true) { // Only show program specific recording button if it hasn't finished yet item { - Button( + TextButton( onClick = { if (isRecording) { onCancelRecord.invoke(false) diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackControls.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackControls.kt index 8e17d2a7..8cb05699 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackControls.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackControls.kt @@ -45,15 +45,13 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogWindowProvider import androidx.media3.common.Player import androidx.media3.common.util.UnstableApi -import androidx.tv.material3.Button -import androidx.tv.material3.ButtonDefaults +import androidx.tv.material3.ClickableSurfaceDefaults import androidx.tv.material3.Icon import androidx.tv.material3.ListItem import androidx.tv.material3.LocalContentColor @@ -62,10 +60,14 @@ import androidx.tv.material3.Text import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.preferences.AppThemeColors import com.github.damontecres.wholphin.ui.AppColors +import com.github.damontecres.wholphin.ui.PreviewTvSpec +import com.github.damontecres.wholphin.ui.components.Button +import com.github.damontecres.wholphin.ui.components.TextButton import com.github.damontecres.wholphin.ui.seekBack import com.github.damontecres.wholphin.ui.seekForward import com.github.damontecres.wholphin.ui.skipStringRes import com.github.damontecres.wholphin.ui.theme.LocalTheme +import com.github.damontecres.wholphin.ui.theme.WholphinTheme import com.github.damontecres.wholphin.ui.tryRequestFocus import com.github.damontecres.wholphin.util.ExceptionHandler import kotlinx.coroutines.delay @@ -192,7 +194,8 @@ fun PlaybackControls( modifier = Modifier.align(Alignment.CenterEnd), ) { currentSegment?.let { segment -> - Button( + TextButton( + stringRes = segment.type.skipStringRes, onClick = { playerControls.seekTo(segment.endTicks.ticks.inWholeMilliseconds) }, @@ -200,11 +203,7 @@ fun PlaybackControls( Modifier .align(Alignment.CenterVertically) .padding(end = 32.dp), - ) { - Text( - text = stringResource(segment.type.skipStringRes), - ) - } + ) } RightPlaybackButtons( captionFocusRequester = captionFocusRequester, @@ -286,7 +285,7 @@ fun SeekBar( } } -private val buttonSpacing = 4.dp +private val buttonSpacing = 12.dp @Composable fun LeftPlaybackButtons( @@ -435,9 +434,9 @@ fun PlaybackButton( Button( enabled = enabled, onClick = onClick, - shape = ButtonDefaults.shape(CircleShape), +// shape = ButtonDefaults.shape(CircleShape), colors = - ButtonDefaults.colors( + ClickableSurfaceDefaults.colors( containerColor = AppColors.TransparentBlack25, focusedContainerColor = selectedColor, ), @@ -445,8 +444,7 @@ fun PlaybackButton( interactionSource = interactionSource, modifier = modifier - .padding(4.dp) - .size(44.dp, 44.dp) + .size(36.dp, 36.dp) .onFocusChanged { onControllerInteraction.invoke() }, ) { Icon( @@ -543,3 +541,17 @@ fun BottomDialog( data class MoreButtonOptions( val options: Map, ) + +@PreviewTvSpec +@Composable +private fun ButtonPreview() { + WholphinTheme { + Row { + PlaybackButton( + iconRes = R.drawable.baseline_play_arrow_24, + onClick = {}, + onControllerInteraction = {}, + ) + } + } +} diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackOverlay.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackOverlay.kt index 1e19ce3d..f92b21f3 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackOverlay.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackOverlay.kt @@ -144,38 +144,72 @@ fun PlaybackOverlay( } else { null } - Controller( - title = item?.title, - subtitle = item?.subtitleLong, - playerControls = playerControls, - controllerViewState = controllerViewState, - showPlay = showPlay, - showClock = showClock, - previousEnabled = previousEnabled, - nextEnabled = nextEnabled, - seekEnabled = seekEnabled, - seekBack = seekBack, - skipBackOnResume = skipBackOnResume, - seekForward = seekForward, - onPlaybackActionClick = onPlaybackActionClick, - onClickPlaybackDialogType = onClickPlaybackDialogType, - onSeekProgress = { - onSeekBarChange(it) - seekProgressMs = it - }, - seekBarInteractionSource = seekBarInteractionSource, - nextState = nextState, - onNextStateFocus = { - nextState?.let { state = it } - }, - currentSegment = currentSegment, + Column( + verticalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier - // Don't use key events because this control has vertical items so up/down is tough to manage + .padding(bottom = 8.dp) .onGloballyPositioned { controllerHeight = with(density) { it.size.height.toDp() } }, - ) + ) { + Controller( + title = item?.title, + subtitle = item?.subtitleLong, + playerControls = playerControls, + controllerViewState = controllerViewState, + showPlay = showPlay, + showClock = showClock, + previousEnabled = previousEnabled, + nextEnabled = nextEnabled, + seekEnabled = seekEnabled, + seekBack = seekBack, + skipBackOnResume = skipBackOnResume, + seekForward = seekForward, + onPlaybackActionClick = onPlaybackActionClick, + onClickPlaybackDialogType = onClickPlaybackDialogType, + onSeekProgress = { + onSeekBarChange(it) + seekProgressMs = it + }, + seekBarInteractionSource = seekBarInteractionSource, + nextState = nextState, + onNextStateFocus = { + nextState?.let { state = it } + }, + currentSegment = currentSegment, + modifier = + Modifier, + // Don't use key events because this control has vertical items so up/down is tough to manage + ) + when (nextState) { + OverlayViewState.CHAPTERS -> + Text( + text = stringResource(R.string.chapters), + style = MaterialTheme.typography.titleLarge, + modifier = + Modifier + .padding(start = 16.dp, top = 0.dp) + .onFocusChanged { + if (it.isFocused) state = nextState + }.focusable(), + ) + + OverlayViewState.QUEUE -> + Text( + text = stringResource(R.string.queue), + style = MaterialTheme.typography.titleLarge, + modifier = + Modifier + .padding(start = 16.dp, top = 0.dp) + .onFocusChanged { + if (it.isFocused) state = nextState + }.focusable(), + ) + + else -> Spacer(Modifier.height(32.dp)) + } + } } AnimatedVisibility( state == OverlayViewState.CHAPTERS, @@ -189,8 +223,8 @@ fun PlaybackOverlay( verticalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier + .padding(horizontal = 8.dp) .fillMaxWidth() - .padding(8.dp) .onPreviewKeyEvent { e -> if (e.type == KeyEventType.KeyUp && isUp(e)) { state = OverlayViewState.CONTROLLER @@ -247,7 +281,7 @@ fun PlaybackOverlay( style = MaterialTheme.typography.titleLarge, modifier = Modifier - .padding(start = 16.dp, top = 16.dp) + .padding(bottom = 8.dp) .onFocusChanged { if (it.isFocused) state = OverlayViewState.QUEUE }.focusable(), @@ -269,8 +303,8 @@ fun PlaybackOverlay( verticalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier - .fillMaxWidth() .padding(8.dp) + .fillMaxWidth() .onPreviewKeyEvent { e -> if (e.type == KeyEventType.KeyUp && isUp(e)) { if (chapters.isNotEmpty()) { @@ -291,7 +325,7 @@ fun PlaybackOverlay( style = MaterialTheme.typography.titleLarge, ) LazyRow( - contentPadding = PaddingValues(16.dp), + contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp), horizontalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier @@ -538,32 +572,5 @@ fun Controller( captionFocusRequester = captionFocusRequester, settingsFocusRequester = settingsFocusRequester, ) - when (nextState) { - OverlayViewState.CHAPTERS -> - Text( - text = stringResource(R.string.chapters), - style = MaterialTheme.typography.titleLarge, - modifier = - Modifier - .padding(start = 16.dp, top = 16.dp) - .onFocusChanged { - if (it.isFocused) onNextStateFocus.invoke() - }.focusable(), - ) - - OverlayViewState.QUEUE -> - Text( - text = stringResource(R.string.queue), - style = MaterialTheme.typography.titleLarge, - modifier = - Modifier - .padding(start = 16.dp, top = 16.dp) - .onFocusChanged { - if (it.isFocused) onNextStateFocus.invoke() - }.focusable(), - ) - - else -> Spacer(Modifier.height(32.dp)) - } } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt index c697a5b0..82bd604f 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt @@ -42,7 +42,6 @@ import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.input.key.onKeyEvent import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView @@ -57,9 +56,7 @@ import androidx.media3.ui.compose.SURFACE_TYPE_SURFACE_VIEW import androidx.media3.ui.compose.modifiers.resizeWithContentScale import androidx.media3.ui.compose.state.rememberPlayPauseButtonState import androidx.media3.ui.compose.state.rememberPresentationState -import androidx.tv.material3.Button import androidx.tv.material3.MaterialTheme -import androidx.tv.material3.Text import androidx.tv.material3.surfaceColorAtElevation import com.github.damontecres.wholphin.data.model.ItemPlayback import com.github.damontecres.wholphin.data.model.Playlist @@ -71,6 +68,7 @@ import com.github.damontecres.wholphin.ui.LocalImageUrlService import com.github.damontecres.wholphin.ui.OneTimeLaunchedEffect import com.github.damontecres.wholphin.ui.components.ErrorMessage import com.github.damontecres.wholphin.ui.components.LoadingPage +import com.github.damontecres.wholphin.ui.components.TextButton import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings.applyToMpv import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings.calculateEdgeSize @@ -403,17 +401,14 @@ fun PlaybackPage( delay(10.seconds) segmentCancelled = true } - Button( + TextButton( + stringRes = segment.type.skipStringRes, onClick = { segmentCancelled = true player.seekTo(segment.endTicks.ticks.inWholeMilliseconds) }, modifier = Modifier.focusRequester(focusRequester), - ) { - Text( - text = stringResource(segment.type.skipStringRes), - ) - } + ) } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/StringInputDialog.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/StringInputDialog.kt index a5e0468f..4229f78d 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/StringInputDialog.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/preferences/StringInputDialog.kt @@ -22,13 +22,13 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties -import androidx.tv.material3.Button import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import androidx.tv.material3.surfaceColorAtElevation import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.ui.components.ConfirmDialog import com.github.damontecres.wholphin.ui.components.EditTextBox +import com.github.damontecres.wholphin.ui.components.TextButton @Composable fun StringInputDialog( @@ -95,22 +95,16 @@ fun StringInputDialog( horizontalArrangement = Arrangement.SpaceAround, modifier = Modifier.fillMaxWidth(), ) { - Button( + TextButton( + stringRes = R.string.cancel, onClick = onDismissRequest, modifier = Modifier, - ) { - Text( - text = stringResource(R.string.cancel), - ) - } - Button( + ) + TextButton( + stringRes = R.string.save, onClick = onDone, modifier = Modifier, - ) { - Text( - text = stringResource(R.string.save), - ) - } + ) } } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt index e81fbce1..dad19712 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt @@ -42,7 +42,6 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import androidx.tv.material3.Button import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import androidx.tv.material3.surfaceColorAtElevation @@ -54,8 +53,10 @@ import com.github.damontecres.wholphin.services.Release import com.github.damontecres.wholphin.services.UpdateChecker import com.github.damontecres.wholphin.ui.PreviewTvSpec import com.github.damontecres.wholphin.ui.components.BasicDialog +import com.github.damontecres.wholphin.ui.components.Button import com.github.damontecres.wholphin.ui.components.ErrorMessage import com.github.damontecres.wholphin.ui.components.LoadingPage +import com.github.damontecres.wholphin.ui.components.TextButton import com.github.damontecres.wholphin.ui.dimAndBlur import com.github.damontecres.wholphin.ui.formatBytes import com.github.damontecres.wholphin.ui.setValueOnMain @@ -299,20 +300,14 @@ fun InstallUpdatePageContent( style = MaterialTheme.typography.titleLarge, color = MaterialTheme.colorScheme.onSurface, ) - Button( + TextButton( + stringRes = R.string.download_and_update, onClick = onInstallRelease, - ) { - Text( - text = stringResource(R.string.download_and_update), - ) - } - Button( + ) + TextButton( + stringRes = R.string.cancel, onClick = onCancel, - ) { - Text( - text = stringResource(R.string.cancel), - ) - } + ) } } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/PinEntry.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/PinEntry.kt index e6ca52a0..e0d49631 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/PinEntry.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/PinEntry.kt @@ -27,13 +27,14 @@ import androidx.compose.ui.input.key.type import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.tv.material3.Button import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.ui.FontAwesome import com.github.damontecres.wholphin.ui.PreviewTvSpec import com.github.damontecres.wholphin.ui.components.BasicDialog +import com.github.damontecres.wholphin.ui.components.Button +import com.github.damontecres.wholphin.ui.components.TextButton import com.github.damontecres.wholphin.ui.playback.isEnterKey import com.github.damontecres.wholphin.ui.theme.WholphinTheme @@ -57,7 +58,7 @@ fun PinEntry( PinArrowRow(Modifier.align(Alignment.CenterHorizontally)) PinEntryDots(input.length, Modifier.align(Alignment.CenterHorizontally)) - Button( + TextButton( onClick = onClickServerAuth, modifier = Modifier diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerContent.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerContent.kt index b8682b0a..c1bc542e 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerContent.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerContent.kt @@ -29,7 +29,6 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel -import androidx.tv.material3.Button import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import androidx.tv.material3.surfaceColorAtElevation @@ -37,6 +36,7 @@ import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.ui.components.BasicDialog import com.github.damontecres.wholphin.ui.components.CircularProgress import com.github.damontecres.wholphin.ui.components.EditTextBox +import com.github.damontecres.wholphin.ui.components.TextButton import com.github.damontecres.wholphin.ui.dimAndBlur import com.github.damontecres.wholphin.ui.isNotNullOrBlank import com.github.damontecres.wholphin.ui.tryRequestFocus @@ -224,7 +224,7 @@ fun SwitchServerContent( else -> {} } - Button( + TextButton( onClick = { submit.invoke() }, enabled = url.text.isNotNullOrBlank() && state == LoadingState.Pending, modifier = Modifier, diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt index 8099b4e4..e0aeb5a1 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt @@ -34,7 +34,6 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel -import androidx.tv.material3.Button import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import androidx.tv.material3.surfaceColorAtElevation @@ -44,6 +43,7 @@ import com.github.damontecres.wholphin.data.model.JellyfinUser import com.github.damontecres.wholphin.ui.components.BasicDialog import com.github.damontecres.wholphin.ui.components.CircularProgress import com.github.damontecres.wholphin.ui.components.EditTextBox +import com.github.damontecres.wholphin.ui.components.TextButton import com.github.damontecres.wholphin.ui.dimAndBlur import com.github.damontecres.wholphin.ui.isNotNullOrBlank import com.github.damontecres.wholphin.ui.nav.Destination @@ -203,16 +203,15 @@ fun SwitchUserContent( ) } UserStateError(userState) - Button( + TextButton( + stringRes = R.string.username_or_password, onClick = { viewModel.cancelQuickConnect() viewModel.clearSwitchUserState() useQuickConnect = false }, modifier = Modifier.align(Alignment.CenterHorizontally), - ) { - Text(text = "Use username/password") - } + ) } else { val username = rememberTextFieldState() val password = rememberTextFieldState() @@ -282,27 +281,25 @@ fun SwitchUserContent( modifier = Modifier.focusRequester(passwordFocusRequester), ) } - Button( + TextButton( + stringRes = R.string.login, onClick = { onSubmit.invoke() }, enabled = username.text.isNotNullOrBlank() && password.text.isNotNullOrBlank(), modifier = Modifier.align(Alignment.CenterHorizontally), - ) { - Text("Login") - } + ) } if (loginAttempts > 2) { Text( text = "Trouble logging in?", modifier = Modifier.align(Alignment.CenterHorizontally), ) - Button( + TextButton( + stringRes = R.string.show_debug_info, onClick = { viewModel.navigationManager.navigateTo(Destination.Debug) }, modifier = Modifier.align(Alignment.CenterHorizontally), - ) { - Text("Show debug info") - } + ) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 40a88eda..6c54c7fb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -350,6 +350,8 @@ Guest stars Edge size + Use username/password + Login