mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-11-05 18:30:59 +01:00
Focus the active profile in the user selector
This commit is contained in:
parent
365f8f8ada
commit
f816ef03ab
2 changed files with 100 additions and 7 deletions
|
|
@ -16,6 +16,7 @@ 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
|
||||
|
|
@ -88,19 +89,24 @@ fun UserList(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
val firstFocusRequester = remember { FocusRequester() }
|
||||
if (users.isNotEmpty()) {
|
||||
LaunchedEffect(Unit) { focusRequester.tryRequestFocus() }
|
||||
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()
|
||||
}
|
||||
}
|
||||
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(firstFocusRequester)
|
||||
.focusRequester(focusRequester),
|
||||
.focusRestorer(initialFocusRequester),
|
||||
) {
|
||||
itemsIndexed(users) { index, user ->
|
||||
UserIconCard(
|
||||
|
|
@ -108,7 +114,7 @@ fun UserList(
|
|||
isCurrentUser = user.user.id == currentUser?.id,
|
||||
onClick = { onSwitchUser.invoke(user.user) },
|
||||
onLongClick = { showDeleteDialog = user },
|
||||
modifier = if (index == 0) Modifier.focusRequester(firstFocusRequester) else Modifier,
|
||||
modifier = if (index == initialIndex) Modifier.focusRequester(initialFocusRequester) else Modifier,
|
||||
)
|
||||
}
|
||||
// Add User card - always rightmost
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
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()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue