diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/component/SearchBar.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/component/SearchBar.kt index 5480adcf4..a2b78c54b 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/component/SearchBar.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/component/SearchBar.kt @@ -24,6 +24,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.SideEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -143,8 +144,14 @@ fun SearchBar( val textFieldValue = remember { mutableStateOf(TextFieldValue(value, TextRange(value.length))) } - if (textFieldValue.value.text != value) { - textFieldValue.value = TextFieldValue(value, TextRange(value.length)) + // Characters the user typed are already in this value; onValueChange below keeps the cursor + // where the user put it. Text that changed from the outside - the search was reset, or a + // character was inserted by the physical keyboard handler - is adopted here, with the cursor at + // the end. This must not write state during composition, so it runs in a side effect after it. + SideEffect { + if (textFieldValue.value.text != value) { + textFieldValue.value = TextFieldValue(value, TextRange(value.length)) + } } LauncherCard(