Keep title destination focus and preserve ready catalogue refreshes

This commit is contained in:
justinzeus 2026-11-07 16:56:49 +01:00
parent 98dd54e03b
commit f9bd630ea7
5 changed files with 23 additions and 10 deletions

View file

@ -6,6 +6,7 @@ import androidx.activity.ComponentActivity
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsFocused
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performKeyInput
@ -69,9 +70,12 @@ class TitleAsyncFocusTest {
rule.setContent { WolfskinTheme { TitleDestination(route, shell, preferences, viewModel = viewModel) } }
rule.waitUntil { viewModel.title?.data?.status == TitleReadStatus.Loading }
rule.waitForIdle()
assertTrue(shell.navFocused)
assertFalse("Loading retains destination focus instead of focusing the root nav", shell.navFocused)
rule.onNodeWithTag("title-page").assertIsFocused()
press(Key.DirectionDown)
assertTrue("The initial skeleton cannot receive nav Down", shell.navFocused)
assertFalse("Down cannot transfer focus to nav or an initial skeleton", shell.navFocused)
assertEquals("header", viewModel.title!!.row)
assertEquals(0, viewModel.title!!.column)
val source = TitleVersion("first", "Original", "1080p", "", "", "MKV", listOf(TitleTrack(3, "English", true)), emptyList())
rule.runOnIdle {
@ -109,9 +113,12 @@ class TitleAsyncFocusTest {
} }
rule.waitUntil { viewModel.title?.data?.status == TitleReadStatus.Loading }
rule.waitForIdle()
assertTrue(shell.navFocused)
assertFalse(shell.navFocused)
rule.onNodeWithTag("title-page").assertIsFocused()
press(Key.DirectionDown)
assertTrue(shell.navFocused)
assertFalse("Down cannot enter a pending person skeleton", shell.navFocused)
assertEquals("header", viewModel.title!!.row)
assertEquals(0, viewModel.title!!.column)
rule.runOnIdle {
reply.complete(org.justinvisser.wolfskin.tv.read.PersonRead(
org.justinvisser.wolfskin.design.TitlePerson(id.toString(), "Actor"),
@ -121,7 +128,7 @@ class TitleAsyncFocusTest {
rule.waitUntil(timeoutMillis = 5000) { viewModel.person != null || viewModel.title?.data?.status == TitleReadStatus.Unavailable }
assertNotNull("A real person reply must populate the performer destination", viewModel.person)
rule.waitForIdle()
assertFalse("The loaded person must transfer nav ownership to its first credit", shell.navFocused)
assertFalse("The loaded person retains destination focus on its first credit", shell.navFocused)
assertEquals(0, viewModel.person!!.index)
press(Key.DirectionRight)
assertEquals(1, viewModel.person!!.index)

View file

@ -90,7 +90,7 @@ class WolfskinTitleViewModel @Inject constructor(
fun load(destination: String, selected: ShellPerson, userPreferences: UserPreferences, fixtures: Boolean = BuildConfig.DEBUG, force: Boolean = false) {
if (!force && route == destination && ::viewer.isInitialized && viewer.key == selected.key) return
if (force && route == destination && ::viewer.isInitialized && viewer.key == selected.key &&
title?.data?.status == TitleReadStatus.Ready && title?.data?.item?.held == true &&
title?.data?.status == TitleReadStatus.Ready &&
(title?.data?.connection != TitleConnection.SignedIn || conductarr.identity.value?.signedIn == true) &&
!destination.startsWith("person/") && fixture == null) {
loadJob?.cancel()