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 <noreply@anthropic.com>
This commit is contained in:
Jeena 2026-10-15 12:22:27 +00:00
parent a6d0f9ec6c
commit e485caa855
2 changed files with 10 additions and 0 deletions

View file

@ -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<VideoChannelDto>,
@ -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),
) {

View file

@ -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<VideoDto>,
@ -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),
) {