Preserve navigation focus when Anime availability changes
Some checks failed
review/code-gpt Anime removal leaves active root invalid; Back pops a singleton stack (B1).
Some checks failed
review/code-gpt Anime removal leaves active root invalid; Back pops a singleton stack (B1).
This commit is contained in:
parent
53b8358317
commit
9e15dbee8c
3 changed files with 12 additions and 2 deletions
|
|
@ -82,13 +82,18 @@ class AnimeAvailabilityTest {
|
||||||
includeItemTypes = listOf(BaseItemKind.SERIES), limit = 1) } returns successQueryResult(titles)
|
includeItemTypes = listOf(BaseItemKind.SERIES), limit = 1) } returns successQueryResult(titles)
|
||||||
val libraries = LibraryReadFacade(api)
|
val libraries = LibraryReadFacade(api)
|
||||||
val session = WolfskinSession().apply {
|
val session = WolfskinSession().apply {
|
||||||
state = ShellState(listOf(ShellPerson(key, key, key.take(1), false, user.id.toString())), key)
|
state = ShellState(listOf(ShellPerson(key, key, key.take(1), count == 0, user.id.toString())), key).apply {
|
||||||
|
pickerVisible = false
|
||||||
|
focusNav(tabs.size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val model = WolfskinShellViewModel(context, session, mockk(), mockk(), mockk(), mockk(relaxed = true),
|
val model = WolfskinShellViewModel(context, session, mockk(), mockk(), mockk(), mockk(relaxed = true),
|
||||||
libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true))
|
libraries, WolfskinSeeAllLists(), conductarr, mockk(relaxed = true))
|
||||||
try {
|
try {
|
||||||
requireNotNull(model.onForeground(server, user)).join()
|
requireNotNull(model.onForeground(server, user)).join()
|
||||||
assertEquals("$key with $count Anime titles", count > 0, "anime" in session.state!!.tabs)
|
assertEquals("$key with $count Anime titles", count > 0, "anime" in session.state!!.tabs)
|
||||||
|
assertEquals("The avatar must remain focused when Anime appears or disappears",
|
||||||
|
session.state!!.tabs.size, session.state!!.navIndex)
|
||||||
val home = HomeLibrary(destinations = mapOf("anime" to titles.map { HomeTitle(it.id.toString(), it.name.orEmpty(), "tv") }),
|
val home = HomeLibrary(destinations = mapOf("anime" to titles.map { HomeTitle(it.id.toString(), it.name.orEmpty(), "tv") }),
|
||||||
destinationTotals = mapOf("anime" to count))
|
destinationTotals = mapOf("anime" to count))
|
||||||
assertEquals("An empty Anime audience must not create a Home shelf", count > 0,
|
assertEquals("An empty Anime audience must not create a Home shelf", count > 0,
|
||||||
|
|
|
||||||
|
|
@ -499,6 +499,8 @@ refresh enables Anime only after a one-title Jellyfin read confirms visible seri
|
||||||
in an accessible Anime library for the signed-in user. This runs after the live
|
in an accessible Anime library for the signed-in user. This runs after the live
|
||||||
picker is published; failures retain that user's last confirmed availability.
|
picker is published; failures retain that user's last confirmed availability.
|
||||||
Empty Anime Home shelves remain omitted.
|
Empty Anime Home shelves remain omitted.
|
||||||
|
When availability changes, focus follows the avatar or a surviving destination;
|
||||||
|
removing Anime never leaves an out-of-range nav selection.
|
||||||
|
|
||||||
| Screen seam | Production supplier |
|
| Screen seam | Production supplier |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
|
|
|
||||||
|
|
@ -50,14 +50,17 @@ class ShellState(
|
||||||
var people by mutableStateOf(people)
|
var people by mutableStateOf(people)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
/** Refresh household labels without discarding this person's navigation memory. */
|
/** Refresh household data without losing valid nav focus or this person's view memory. */
|
||||||
fun updatePeople(value: List<ShellPerson>) {
|
fun updatePeople(value: List<ShellPerson>) {
|
||||||
|
val focusedTab = tabs.getOrNull(navIndex)
|
||||||
|
val avatarFocused = navIndex == tabs.size
|
||||||
val selected = value.firstOrNull { it.jellyfinUserId != null && it.jellyfinUserId == person.jellyfinUserId }
|
val selected = value.firstOrNull { it.jellyfinUserId != null && it.jellyfinUserId == person.jellyfinUserId }
|
||||||
?: value.firstOrNull { it.key == person.key }
|
?: value.firstOrNull { it.key == person.key }
|
||||||
people = value
|
people = value
|
||||||
if (selected != null) person = selected
|
if (selected != null) person = selected
|
||||||
pickerIndex = people.indexOf(person).coerceAtLeast(0)
|
pickerIndex = people.indexOf(person).coerceAtLeast(0)
|
||||||
preparePersonMemory()
|
preparePersonMemory()
|
||||||
|
navIndex = if (avatarFocused) tabs.size else tabs.indexOf(focusedTab).takeIf { it >= 0 } ?: currentTab
|
||||||
}
|
}
|
||||||
var person by mutableStateOf(people.firstOrNull { it.key == initialPerson } ?: people.first())
|
var person by mutableStateOf(people.firstOrNull { it.key == initialPerson } ?: people.first())
|
||||||
private set
|
private set
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue