Start new Home rows leftmost and gate outgoing Back handlers

This commit is contained in:
justinzeus 2026-11-07 18:52:30 +01:00
parent 5811ab0555
commit c5dbe91076
7 changed files with 82 additions and 32 deletions

View file

@ -105,13 +105,15 @@ class HomeKeysTest {
assertNull(action)
}
@Test fun downClampsToShortRowsAndNeverMovesPastTheFinalSeeAll() {
@Test fun rememberedColumnsClampToShortRowsAndTheFinalSeeAll() {
val shell = ShellState(fixturePeople(), "justin").apply { pickerVisible = false; navFocused = false }
val cards = HomeFixture(rule.activity).snapshot("justin").rows.first { it.id == "lib-movies" }.cards
val long = HomeRow(id = "long", kind = HomeRowKind.Shelf, cards = cards)
val short = long.copy(id = "short", cards = cards.take(2), total = 2)
val tail = short.copy(id = "tail", total = 20)
shell.view.cards[long.id] = cards.lastIndex
shell.view.cards[short.id] = cards.lastIndex
shell.view.cards[tail.id] = 2
var action: HomeAction? = null
rule.setContent { WolfskinTheme {
ShellSurface(shell) { modifier -> HomeScreen(shell, HomeSnapshot(listOf(long, short, tail)), modifier) { action = it } }
@ -132,17 +134,18 @@ class HomeKeysTest {
assertEquals(tail.id, (action as HomeAction.SeeAll).row.id)
}
@Test fun mixedWidthRowsUseNearestCenterAndKeepTheTrackWhenMovingBackInsideItsMiddle() {
@Test fun visitedMixedWidthRowsKeepColumnsAndTrackWhenMovingInsideTheMiddle() {
val shell = ShellState(fixturePeople(), "justin").apply { pickerVisible = false; navFocused = false }
val cards = HomeFixture(rule.activity).snapshot("justin").rows.first { it.id == "lib-movies" }.cards
val posters = HomeRow(id = "posters", kind = HomeRowKind.Shelf, cards = cards)
val tiles = posters.copy(id = "tiles", cardKind = HomeCardKind.Tile)
shell.view.cards[posters.id] = 3
shell.view.cards[tiles.id] = 2
rule.setContent { WolfskinTheme {
ShellSurface(shell) { modifier -> HomeScreen(shell, HomeSnapshot(listOf(posters, tiles)), modifier) {} }
} }
press("DOWN")
assertEquals("The third tile is nearest the fourth poster's horizontal center", 2, shell.view.cards[tiles.id])
assertEquals(2, shell.view.cards[tiles.id])
repeat(4) { press("RIGHT") }
val left = rule.onNodeWithTag("home-card:tiles:4").fetchSemanticsNode().boundsInRoot.left
press("LEFT")

View file

@ -0,0 +1,61 @@
package org.justinvisser.wolfskin.design
import android.app.Application
import androidx.compose.foundation.lazy.LazyListState
import org.junit.Assert.*
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
/** Home starts new rows at zero and retains visited positions independently of other root tabs. */
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [34], application = Application::class)
class HomeRowEntryTest {
private val people = listOf(ShellPerson("justin", "Justin", "J", true))
private val cards = List(12) { HomeTitle("item-$it", "Film $it", "movie") }
@Test fun unvisitedRowsStartLeftmostAcrossCardWidths() {
for (from in HomeCardKind.entries) for (to in HomeCardKind.entries) {
val shell = ShellState(people, "justin").apply { pickerVisible = false; navFocused = false }
val source = HomeRow("source", HomeRowKind.Shelf, cards = cards, cardKind = from)
val target = source.copy(id = "target", cardKind = to)
val focus = HomeFocus(shell, listOf(source, target)) {}
focus.focus(0, 3)
focus.key(ShellKey.Down)
assertEquals("$from to $to", target.id, focus.row?.id)
assertEquals("$from to $to must start leftmost", 0, focus.column)
assertEquals(0, shell.rememberedView("home").home.firstCards[target.id])
}
}
@Test fun visitedColumnsAndFirstVisiblePositionsSurviveRowChangesAndRootTabLeave() {
val shell = ShellState(people, "justin").apply { pickerVisible = false; navFocused = false }
val source = HomeRow("source", HomeRowKind.Shelf, cards = cards)
val rows = listOf(source, source.copy(id = "target", cardKind = HomeCardKind.Tile))
val focus = HomeFocus(shell, rows) {}
focus.focus(0, 8)
focus.key(ShellKey.Left)
val view = shell.rememberedView("home")
val first = view.home.firstCards.getValue(source.id)
val track = LazyListState(first, 19)
view.home.tracks[source.id] = track
focus.key(ShellKey.Down)
focus.key(ShellKey.Up)
assertEquals(7, focus.column)
assertEquals(first, view.home.firstCards[source.id])
shell.focusNav(shell.tabs.indexOf("discover")); shell.key(ShellKey.Ok)
shell.focusNav(shell.tabs.indexOf("home")); shell.key(ShellKey.Ok)
val restored = HomeFocus(shell, rows) {}
assertSame(view, shell.rememberedView("home"))
assertEquals(7, restored.column)
restored.key(ShellKey.Down)
restored.key(ShellKey.Up)
assertEquals(7, restored.column)
assertEquals(first, view.home.firstCards[source.id])
assertSame(track, view.home.tracks[source.id])
assertEquals(first, track.firstVisibleItemIndex)
assertEquals(19, track.firstVisibleItemScrollOffset)
}
}