fix(authscreen): keyboard to dismiss while tapping outside

fixes #1138
This commit is contained in:
tapframe 2026-05-27 11:39:57 +05:30
parent 0c0c616bed
commit 1d7bdd60f9

View file

@ -7,6 +7,8 @@ import androidx.compose.animation.togetherWith
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@ -40,13 +42,21 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInRoot
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
@ -85,18 +95,34 @@ fun AuthScreen(
) {
val authError by AuthRepository.error.collectAsStateWithLifecycle()
val scope = rememberCoroutineScope()
val focusManager = LocalFocusManager.current
var isSignUp by rememberSaveable { mutableStateOf(false) }
var email by rememberSaveable { mutableStateOf("") }
var password by rememberSaveable { mutableStateOf("") }
var passwordVisible by rememberSaveable { mutableStateOf(false) }
var isLoading by rememberSaveable { mutableStateOf(false) }
var emailFieldBounds by remember { mutableStateOf<Rect?>(null) }
var passwordFieldBounds by remember { mutableStateOf<Rect?>(null) }
val statusBarTop = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
Box(
modifier = modifier
.fillMaxSize()
.background(Color.Black),
.background(Color.Black)
.pointerInput(emailFieldBounds, passwordFieldBounds) {
awaitEachGesture {
val down = awaitFirstDown(
requireUnconsumed = false,
pass = PointerEventPass.Initial,
)
val tappedTextField = listOfNotNull(emailFieldBounds, passwordFieldBounds)
.any { bounds -> bounds.contains(down.position) }
if (!tappedTextField) {
focusManager.clearFocus(force = true)
}
}
},
) {
Box(
modifier = Modifier
@ -162,7 +188,11 @@ fun AuthScreen(
email = it
AuthRepository.clearError()
},
modifier = Modifier.fillMaxWidth(),
modifier = Modifier
.fillMaxWidth()
.onGloballyPositioned { coordinates ->
emailFieldBounds = coordinates.boundsInRoot()
},
singleLine = true,
placeholder = {
Text(
@ -195,7 +225,11 @@ fun AuthScreen(
password = it
AuthRepository.clearError()
},
modifier = Modifier.fillMaxWidth(),
modifier = Modifier
.fillMaxWidth()
.onGloballyPositioned { coordinates ->
passwordFieldBounds = coordinates.boundsInRoot()
},
singleLine = true,
placeholder = {
Text(
@ -386,3 +420,13 @@ fun AuthScreen(
}
}
}
private fun LayoutCoordinates.boundsInRoot(): Rect {
val position = positionInRoot()
return Rect(
left = position.x,
top = position.y,
right = position.x + size.width,
bottom = position.y + size.height,
)
}