diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/UserList.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/UserList.kt index 4d3ff8d3..ddc171c9 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/UserList.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/UserList.kt @@ -16,7 +16,6 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add @@ -89,24 +88,19 @@ fun UserList( modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center, ) { - val listState = rememberLazyListState() - val initialFocusRequester = remember { FocusRequester() } - val initialIndex = - users.indexOfFirst { it.user.id == currentUser?.id }.takeIf { it >= 0 } ?: 0 - LaunchedEffect(users, currentUser?.id) { - if (users.isNotEmpty()) { - listState.scrollToItem(initialIndex) - initialFocusRequester.tryRequestFocus() - } + val focusRequester = remember { FocusRequester() } + val firstFocusRequester = remember { FocusRequester() } + if (users.isNotEmpty()) { + LaunchedEffect(Unit) { focusRequester.tryRequestFocus() } } LazyRow( - state = listState, horizontalArrangement = Arrangement.spacedBy(24.dp), // Spacing to accommodate 20% scale contentPadding = PaddingValues(horizontal = 48.dp, vertical = 16.dp), // Increased padding to accommodate 20% scale modifier = Modifier .wrapContentWidth() - .focusRestorer(initialFocusRequester), + .focusRestorer(firstFocusRequester) + .focusRequester(focusRequester), ) { itemsIndexed(users) { index, user -> UserIconCard( @@ -114,7 +108,7 @@ fun UserList( isCurrentUser = user.user.id == currentUser?.id, onClick = { onSwitchUser.invoke(user.user) }, onLongClick = { showDeleteDialog = user }, - modifier = if (index == initialIndex) Modifier.focusRequester(initialFocusRequester) else Modifier, + modifier = if (index == 0) Modifier.focusRequester(firstFocusRequester) else Modifier, ) } // Add User card - always rightmost diff --git a/app/src/test/java/com/github/damontecres/wholphin/ui/setup/UserListFocusTest.kt b/app/src/test/java/com/github/damontecres/wholphin/ui/setup/UserListFocusTest.kt deleted file mode 100644 index a6a23244..00000000 --- a/app/src/test/java/com/github/damontecres/wholphin/ui/setup/UserListFocusTest.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.github.damontecres.wholphin.ui.setup - -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.key.Key -import androidx.compose.ui.test.assertIsFocused -import androidx.compose.ui.test.junit4.createComposeRule -import androidx.compose.ui.test.onNodeWithText -import androidx.compose.ui.test.performKeyInput -import androidx.compose.ui.test.pressKey -import com.github.damontecres.wholphin.data.model.JellyfinUser -import com.github.damontecres.wholphin.ui.theme.WholphinTheme -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config -import java.util.UUID - -@Config(sdk = [34]) -@RunWith(RobolectricTestRunner::class) -class UserListFocusTest { - @get:Rule val composeTestRule = createComposeRule() - - private val serverId = UUID.fromString("00000000-0000-0000-0000-000000000010") - private val users = - listOf("Ada", "Bert", "Cleo").mapIndexed { index, name -> - JellyfinUserAndImage( - user = - JellyfinUser( - id = UUID(0, (index + 1).toLong()), - name = name, - serverId = serverId, - accessToken = "token", - ), - imageUrl = null, - known = true, - ) - } - - private fun showUsers(currentUser: JellyfinUser?) { - composeTestRule.setContent { - WholphinTheme { - UserList( - users = users, - currentUser = currentUser, - onSwitchUser = {}, - onAddUser = {}, - onRemoveUser = {}, - onSwitchServer = {}, - modifier = Modifier.fillMaxSize(), - ) - } - } - } - - @Test - fun `opening selector focuses active profile and supports D-pad navigation`() { - showUsers(users[1].user) - - composeTestRule.onNodeWithText("B").assertIsFocused().performKeyInput { - pressKey(Key.DirectionRight) - } - composeTestRule.onNodeWithText("C").assertIsFocused() - } - - @Test - fun `opening selector scrolls to an active profile outside the initial viewport`() { - showUsers(users[2].user) - - composeTestRule.onNodeWithText("C").assertIsFocused() - } - - @Test - fun `opening selector without a listed active profile focuses first profile`() { - showUsers(null) - - composeTestRule.onNodeWithText("A").assertIsFocused() - } - - @Test - fun `opening selector with a removed active profile focuses first profile`() { - showUsers(users[1].user.copy(id = UUID(0, 99))) - - composeTestRule.onNodeWithText("A").assertIsFocused() - } -}