From e485caa855028b70c6b9fed15ef4b61ef02f134c Mon Sep 17 00:00:00 2001 From: Jeena Date: Thu, 15 Oct 2026 12:22:27 +0000 Subject: [PATCH] rows: restore the last-focused card when moving between rows (#29) Moving up/down between the Home rows (and the Channels rows) jumped to the geometrically-nearest card, so the row shifted left/right and felt inconsistent. A focusRestorer on each row now lands focus on the card that row last had, so the rows stay put as you move between them. Co-Authored-By: Claude Opus 4.8 --- .../java/net/jeena/jtubetv/ui/screens/ChannelsScreen.kt | 4 ++++ app/src/main/java/net/jeena/jtubetv/ui/screens/HomeRows.kt | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/app/src/main/java/net/jeena/jtubetv/ui/screens/ChannelsScreen.kt b/app/src/main/java/net/jeena/jtubetv/ui/screens/ChannelsScreen.kt index 203fbf7..603a561 100644 --- a/app/src/main/java/net/jeena/jtubetv/ui/screens/ChannelsScreen.kt +++ b/app/src/main/java/net/jeena/jtubetv/ui/screens/ChannelsScreen.kt @@ -37,6 +37,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip 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.onPreviewKeyEvent @@ -439,6 +440,7 @@ private fun absoluteAvatar(avatar: Avatar): String = } /** Horizontal row of channel cards, eased scroll-in; LEFT at row start -> drawer. */ +@OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class) @Composable private fun ChannelRow( channels: List, @@ -481,6 +483,8 @@ private fun ChannelRow( LazyRow( state = rowState, + // Land on the last-focused card when moving between rows (issue #29). + modifier = Modifier.focusRestorer { focusRequesters[focusedIndex.coerceAtLeast(0)] ?: FocusRequester.Default }, contentPadding = PaddingValues(horizontal = 12.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), ) { diff --git a/app/src/main/java/net/jeena/jtubetv/ui/screens/HomeRows.kt b/app/src/main/java/net/jeena/jtubetv/ui/screens/HomeRows.kt index bca62ff..83007c0 100644 --- a/app/src/main/java/net/jeena/jtubetv/ui/screens/HomeRows.kt +++ b/app/src/main/java/net/jeena/jtubetv/ui/screens/HomeRows.kt @@ -14,6 +14,7 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.focus.focusRestorer import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -424,6 +425,7 @@ fun ShimmerRow(size: Int = 4) { * viewport, the row animates it to the left edge (SmartTube behaviour) instead of * the abrupt jump the built-in lazy scroll produces. */ +@OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class) @Composable fun FocusScrollRow( videos: List, @@ -489,6 +491,10 @@ fun FocusScrollRow( } LazyRow( state = rowState, + // Jumping between rows lands on the card this row last had focus on, not + // the geometrically-nearest one (issue #29): the rows stop shifting + // left/right as you move up and down between them. + modifier = Modifier.focusRestorer { focusRequesters[focusedIndex.coerceAtLeast(0)] ?: FocusRequester.Default }, contentPadding = PaddingValues(horizontal = 12.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), ) {