Compare commits
1 Commits
v1.40.2-ty
...
v1.40.2-ty
| Author | SHA1 | Date | |
|---|---|---|---|
| 5c1e9c5bf2 |
@@ -34,8 +34,8 @@ android {
|
||||
applicationId = "de.mm20.launcher2"
|
||||
minSdk = libs.versions.minSdk.get().toInt()
|
||||
targetSdk = libs.versions.targetSdk.get().toInt()
|
||||
versionCode = System.getenv("VERSION_CODE_OVERRIDE")?.toIntOrNull() ?: 2026091002
|
||||
versionName = "1.40.2-typing.3"
|
||||
versionCode = System.getenv("VERSION_CODE_OVERRIDE")?.toIntOrNull() ?: 2026091003
|
||||
versionName = "1.40.2-typing.4"
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -1074,14 +1075,25 @@ internal fun LauncherScaffold(
|
||||
|
||||
// Open the search when the user starts typing on a physical keyboard. The handler is
|
||||
// installed on the activity, so it also receives key events while no text field is focused.
|
||||
val typeToSearchHandler = rememberTypeToSearchHandler(state, searchVM)
|
||||
DisposableEffect(typeToSearchHandler) {
|
||||
val launcherActivity = activity as? SharedLauncherActivity
|
||||
launcherActivity?.launcherKeyEventHandler = typeToSearchHandler
|
||||
//
|
||||
// The scaffold state is recreated when one of its keys changes - the window size after a
|
||||
// rotation, or the state that rememberSaveable restores after the activity was recreated -
|
||||
// so the handler must not keep a reference to one particular instance: it reads the current
|
||||
// state through this holder, which the composition keeps up to date, and the activity's
|
||||
// handler is refreshed on every composition. Without that, the handler can end up opening
|
||||
// the search on a state that is no longer the one that is rendered, which looks as if the
|
||||
// key press did nothing.
|
||||
val currentState = remember { mutableStateOf(state) }
|
||||
SideEffect {
|
||||
if (currentState.value !== state) currentState.value = state
|
||||
}
|
||||
val typeToSearchHandler = rememberTypeToSearchHandler({ currentState.value }, searchVM)
|
||||
SideEffect {
|
||||
(activity as? SharedLauncherActivity)?.launcherKeyEventHandler = typeToSearchHandler
|
||||
}
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
if (launcherActivity?.launcherKeyEventHandler === typeToSearchHandler) {
|
||||
launcherActivity.launcherKeyEventHandler = null
|
||||
}
|
||||
(activity as? SharedLauncherActivity)?.launcherKeyEventHandler = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,9 @@ internal fun KeyEvent.isEnter(): Boolean {
|
||||
* [SharedLauncherActivity.launcherKeyEventHandler]. It is called for every key event before the
|
||||
* event is dispatched to the view hierarchy, so it also works while no text field has focus.
|
||||
*
|
||||
* The scaffold state the handler works on is passed as a provider rather than as a value, because
|
||||
* the state is replaced when the window size changes or the launcher is recreated.
|
||||
*
|
||||
* While the search is driven by the physical keyboard, the search bar's text field is deliberately
|
||||
* left unfocused: a focused text field would make the system show the on-screen keyboard, and the
|
||||
* user is typing on a physical keyboard anyway. The handler therefore inserts and deletes the
|
||||
@@ -68,7 +71,7 @@ internal fun KeyEvent.isEnter(): Boolean {
|
||||
*/
|
||||
@Composable
|
||||
internal fun rememberTypeToSearchHandler(
|
||||
state: LauncherScaffoldState,
|
||||
stateProvider: () -> LauncherScaffoldState,
|
||||
searchVM: SearchVM,
|
||||
): (KeyEvent) -> Boolean {
|
||||
val scope = rememberCoroutineScope()
|
||||
@@ -76,8 +79,12 @@ internal fun rememberTypeToSearchHandler(
|
||||
val sheetManager = LocalBottomSheetManager.current
|
||||
val overlayManager = LocalOverlayManager.current
|
||||
|
||||
return remember(state, searchVM, activity, sheetManager, overlayManager) {
|
||||
// Deliberately not keyed on the scaffold state: the state is recreated when the window is
|
||||
// resized or the launcher is recreated, and a key must always be handled by the state that is
|
||||
// rendered at that moment. stateProvider hands out that state.
|
||||
return remember(searchVM, activity, sheetManager, overlayManager) {
|
||||
fun handle(event: KeyEvent): Boolean {
|
||||
val state = stateProvider()
|
||||
// Read the preference here rather than capturing it in the composition, so that the
|
||||
// current value is always used.
|
||||
if (!searchVM.searchOnTyping.value || state.isLocked) return false
|
||||
|
||||
Reference in New Issue
Block a user