OXYGENHUB

The filter on Repositories takes focus only when touched (closes #12) 75ceba747960

Tapping a destination in the navigation bar gives the app's view focus,
which Compose hands to the screen's first focusable: the filter, so the
keyboard came up on every visit to Repositories. The filter can now take
focus only once touched, or when the device is used from a keyboard.
Checked on a Pixel 10 Pro Fold over adb: no keyboard on opening, the
keyboard on tapping the filter, filtering as before.
Author
Andy McCall @andymccall <[email protected]>
via
agent agent:claude@andymccall <[email protected]> · keyless, under your grant for changes,refs,seal · key 62e60420377a
When
· 2026-10-25 11:03 UTC
Signature
◈ sealed by agent:claude@andymccall
Hash
75ceba7479600e5cf590b136c67b90c2299cf47ed5b86ebb6fc0a2ff8daf55a1
Depends on
144cbf7bf2b5
Depended on by
821035db5a1c
In bookmarks
main
In tags
v0.1.0 v0.1.1 v0.1.2 v0.1.3 v0.1.4 v0.1.5 v0.1.6 v0.1.7 v0.1.8 v0.1.9
Edits
4 atoms, 0 tree operations, 1 file

Browse the tree at this change

modified app/src/main/java/io/oxygenhub/android/ui/repos/RepositoriesScreen.kt +31 −1
…
28 unchanged lines
29 29
import androidx.compose.runtime.getValue
30 30
import androidx.compose.runtime.rememberCoroutineScope
31 31
import androidx.compose.ui.Modifier
32 +
import androidx.compose.foundation.gestures.awaitEachGesture
33 +
import androidx.compose.foundation.gestures.awaitFirstDown
34 +
import androidx.compose.runtime.mutableStateOf
35 +
import androidx.compose.runtime.remember
36 +
import androidx.compose.runtime.setValue
37 +
import androidx.compose.ui.composed
38 +
import androidx.compose.ui.focus.focusProperties
39 +
import androidx.compose.ui.input.InputMode
40 +
import androidx.compose.ui.input.pointer.PointerEventPass
41 +
import androidx.compose.ui.input.pointer.pointerInput
42 +
import androidx.compose.ui.platform.LocalInputModeManager
32 43
import androidx.compose.ui.unit.dp
33 44
import androidx.lifecycle.compose.collectAsStateWithLifecycle
34 45
import androidx.window.core.layout.WindowSizeClass
…
45 unchanged lines
80 91
    )
81 92
}
82 93
94 +
/**
95 +
 * Focus only when touched (or reached from a keyboard): tapping a
96 +
 * destination in the navigation bar gives the app's view focus, which
97 +
 * Compose passes on to the screen's first focusable, and this filter then
98 +
 * took it and brought the keyboard up on every visit (#12).
99 +
 */
100 +
private fun Modifier.focusedOnlyWhenTouched(): Modifier = composed {
101 +
    val keyboard = LocalInputModeManager.current.inputMode == InputMode.Keyboard
102 +
    var touched by remember { mutableStateOf(false) }
103 +
    this
104 +
        .pointerInput(Unit) {
105 +
            awaitEachGesture {
106 +
                awaitFirstDown(requireUnconsumed = false, pass = PointerEventPass.Initial)
107 +
                touched = true
108 +
            }
109 +
        }
110 +
        .focusProperties { canFocus = touched || keyboard }
111 +
}
112 +
83 113
@Composable
84 114
private fun RepositoryList(vm: RepositoriesViewModel, selected: String?, onOpen: (Repository) -> Unit) {
85 115
    val state by vm.state.collectAsStateWithLifecycle()
…
6 unchanged lines
92 122
                placeholder = { Text("Filter") },
93 123
                leadingIcon = { Icon(Icons.Outlined.Search, contentDescription = null) },
94 124
                singleLine = true,
95 -
                modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
125 +
                modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp).focusedOnlyWhenTouched(),
96 126
            )
97 127
            Row(Modifier.padding(horizontal = 16.dp, vertical = 8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
98 128
                FilterChip(query.filter == RepoFilter.Yours, onClick = { vm.setFilter(RepoFilter.Yours) }, label = { Text("Yours") })
…
27 unchanged lines