diff --git a/app/src/main/kotlin/com/arflix/tv/ui/components/SettingsRows.kt b/app/src/main/kotlin/com/arflix/tv/ui/components/SettingsRows.kt new file mode 100644 index 00000000..3b8c2dee --- /dev/null +++ b/app/src/main/kotlin/com/arflix/tv/ui/components/SettingsRows.kt @@ -0,0 +1,193 @@ +package com.arflix.tv.ui.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.tv.material3.ExperimentalTvMaterial3Api +import com.arflix.tv.ui.theme.ArflixTypography +import com.arflix.tv.ui.theme.Pink +import com.arflix.tv.ui.theme.SuccessGreen +import com.arflix.tv.ui.theme.TextPrimary +import com.arflix.tv.ui.theme.TextSecondary +import com.arflix.tv.ui.skin.resolveAccentColor + +@OptIn(ExperimentalTvMaterial3Api::class) +@Composable +fun SettingsRow( + icon: ImageVector, + title: String, + subtitle: String = "", + value: String, + isFocused: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier +) { + val interactionSource = remember { MutableInteractionSource() } + val focusRingColor = resolveAccentColor(fallback = Pink) + Row( + modifier = modifier + .fillMaxWidth() + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = onClick + ) + .background( + if (isFocused) Color.White.copy(alpha = 0.12f) else Color.White.copy(alpha = 0.05f), + RoundedCornerShape(12.dp) + ) + .border( + width = if (isFocused) 2.dp else 0.dp, + color = if (isFocused) focusRingColor else Color.Transparent, + shape = RoundedCornerShape(12.dp) + ) + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.weight(1f)) { + Icon( + imageVector = icon, + contentDescription = null, + tint = TextSecondary, + modifier = Modifier.size(19.dp) + ) + Spacer(modifier = Modifier.width(12.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + style = ArflixTypography.cardTitle.copy(fontSize = 16.sp), + color = TextPrimary, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + if (subtitle.isNotEmpty()) { + Text( + text = subtitle, + style = ArflixTypography.caption.copy(fontSize = 13.sp), + color = TextSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } + Spacer(modifier = Modifier.width(12.dp)) + + if (value.isNotBlank()) { + Box( + modifier = Modifier + .background(Pink.copy(alpha = 0.15f), RoundedCornerShape(999.dp)) + .border(1.dp, Pink.copy(alpha = 0.3f), RoundedCornerShape(999.dp)) + .padding(horizontal = 12.dp, vertical = 6.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = value.uppercase(), + style = ArflixTypography.label.copy(fontSize = 11.sp, letterSpacing = 0.5.sp), + color = Pink, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } +} + +@OptIn(ExperimentalTvMaterial3Api::class) +@Composable +fun SettingsToggleRow( + title: String, + subtitle: String, + isEnabled: Boolean, + isFocused: Boolean, + onToggle: (Boolean) -> Unit, + modifier: Modifier = Modifier +) { + val interactionSource = remember { MutableInteractionSource() } + val focusRingColor = resolveAccentColor(fallback = Pink) + Row( + modifier = modifier + .fillMaxWidth() + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = { onToggle(!isEnabled) } + ) + .background( + if (isFocused) Color.White.copy(alpha = 0.12f) else Color.White.copy(alpha = 0.05f), + RoundedCornerShape(12.dp) + ) + .border( + width = if (isFocused) 2.dp else 0.dp, + color = if (isFocused) focusRingColor else Color.Transparent, + shape = RoundedCornerShape(12.dp) + ) + .padding(horizontal = 16.dp, vertical = 14.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + style = ArflixTypography.cardTitle.copy(fontSize = 16.sp), + color = TextPrimary, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + if (subtitle.isNotEmpty()) { + Text( + text = subtitle, + style = ArflixTypography.caption.copy(fontSize = 13.sp), + color = TextSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + + Box( + modifier = Modifier + .width(44.dp) + .height(24.dp) + .background( + color = if (isEnabled) SuccessGreen else Color.White.copy(alpha = 0.2f), + shape = RoundedCornerShape(13.dp) + ) + .padding(3.dp), + contentAlignment = if (isEnabled) Alignment.CenterEnd else Alignment.CenterStart + ) { + Box( + modifier = Modifier + .size(18.dp) + .background( + color = Color.White, + shape = RoundedCornerShape(10.dp) + ) + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/arflix/tv/ui/screens/settings/SettingsScreen.kt b/app/src/main/kotlin/com/arflix/tv/ui/screens/settings/SettingsScreen.kt index d75bb23f..d8570753 100644 --- a/app/src/main/kotlin/com/arflix/tv/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/kotlin/com/arflix/tv/ui/screens/settings/SettingsScreen.kt @@ -138,6 +138,8 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.viewinterop.AndroidView +import com.arflix.tv.ui.components.SettingsRow +import com.arflix.tv.ui.components.SettingsToggleRow import androidx.core.widget.doAfterTextChanged import androidx.hilt.navigation.compose.hiltViewModel import androidx.tv.material3.ExperimentalTvMaterial3Api @@ -5893,165 +5895,6 @@ private fun IptvSettings( } } -@OptIn(ExperimentalTvMaterial3Api::class) -@Composable -private fun SettingsRow( - icon: ImageVector, - title: String, - subtitle: String = "", - value: String, - isFocused: Boolean, - onClick: () -> Unit, - modifier: Modifier = Modifier -) { - val interactionSource = remember { MutableInteractionSource() } - val focusRingColor = resolveAccentColor(fallback = Pink) - Row( - modifier = modifier - .fillMaxWidth() - .clickable( - interactionSource = interactionSource, - indication = null, - onClick = onClick - ) - .background( - if (isFocused) Color.White.copy(alpha = 0.12f) else Color.White.copy(alpha = 0.05f), - RoundedCornerShape(12.dp) - ) - .border( - width = if (isFocused) 2.dp else 0.dp, - color = if (isFocused) focusRingColor else Color.Transparent, - shape = RoundedCornerShape(12.dp) - ) - .padding(horizontal = 16.dp, vertical = 14.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.weight(1f)) { - Icon( - imageVector = icon, - contentDescription = null, - tint = TextSecondary, - modifier = Modifier.size(19.dp) - ) - Spacer(modifier = Modifier.width(12.dp)) - Column(modifier = Modifier.weight(1f)) { - Text( - text = title, - style = ArflixTypography.cardTitle.copy(fontSize = 16.sp), - color = TextPrimary, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - if (subtitle.isNotEmpty()) { - Text( - text = subtitle, - style = ArflixTypography.caption.copy(fontSize = 13.sp), - color = TextSecondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } - } - } - Spacer(modifier = Modifier.width(12.dp)) - - if (value.isNotBlank()) { - Box( - modifier = Modifier - .background(Pink.copy(alpha = 0.15f), RoundedCornerShape(999.dp)) - .border(1.dp, Pink.copy(alpha = 0.3f), RoundedCornerShape(999.dp)) - .padding(horizontal = 12.dp, vertical = 6.dp), - contentAlignment = Alignment.Center - ) { - Text( - text = value.uppercase(), - style = ArflixTypography.label.copy(fontSize = 11.sp, letterSpacing = 0.5.sp), - color = Pink, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } - } - } -} - -@OptIn(ExperimentalTvMaterial3Api::class) -@Composable -private fun SettingsToggleRow( - title: String, - subtitle: String, - isEnabled: Boolean, - isFocused: Boolean, - onToggle: (Boolean) -> Unit, - modifier: Modifier = Modifier -) { - val interactionSource = remember { MutableInteractionSource() } - val focusRingColor = resolveAccentColor(fallback = Pink) - Row( - modifier = modifier - .fillMaxWidth() - .clickable( - interactionSource = interactionSource, - indication = null, - onClick = { onToggle(!isEnabled) } - ) - .background( - if (isFocused) Color.White.copy(alpha = 0.12f) else Color.White.copy(alpha = 0.05f), - RoundedCornerShape(12.dp) - ) - .border( - width = if (isFocused) 2.dp else 0.dp, - color = if (isFocused) focusRingColor else Color.Transparent, - shape = RoundedCornerShape(12.dp) - ) - .padding(horizontal = 16.dp, vertical = 14.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Column(modifier = Modifier.weight(1f)) { - Text( - text = title, - style = ArflixTypography.cardTitle.copy(fontSize = 16.sp), - color = TextPrimary, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - if (subtitle.isNotEmpty()) { - Text( - text = subtitle, - style = ArflixTypography.caption.copy(fontSize = 13.sp), - color = TextSecondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } - } - - // Custom toggle indicator instead of Switch - Box( - modifier = Modifier - .width(44.dp) - .height(24.dp) - .background( - color = if (isEnabled) SuccessGreen else Color.White.copy(alpha = 0.2f), - shape = RoundedCornerShape(13.dp) - ) - .padding(3.dp), - contentAlignment = if (isEnabled) Alignment.CenterEnd else Alignment.CenterStart - ) { - Box( - modifier = Modifier - .size(18.dp) - .background( - color = Color.White, - shape = RoundedCornerShape(10.dp) - ) - ) - } - } -} - @OptIn(ExperimentalTvMaterial3Api::class) @Composable private fun CatalogDiscoveryModal(