diff --git a/app/src/main/java/com/rosetta/messenger/ui/components/SwipeBackContainer.kt b/app/src/main/java/com/rosetta/messenger/ui/components/SwipeBackContainer.kt index 3c40cfd..23a13d7 100644 --- a/app/src/main/java/com/rosetta/messenger/ui/components/SwipeBackContainer.kt +++ b/app/src/main/java/com/rosetta/messenger/ui/components/SwipeBackContainer.kt @@ -1,5 +1,6 @@ package com.rosetta.messenger.ui.components +import android.app.Activity import android.content.Context import android.view.animation.DecelerateInterpolator import android.view.inputmethod.InputMethodManager @@ -20,9 +21,11 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalView import androidx.compose.ui.unit.dp +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch import kotlin.coroutines.coroutineContext // Telegram's CubicBezierInterpolator(0.25, 0.1, 0.25, 1.0) @@ -174,6 +177,15 @@ fun SwipeBackContainer( val context = LocalContext.current val view = LocalView.current val focusManager = LocalFocusManager.current + val dismissKeyboard: () -> Unit = { + val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(view.windowToken, 0) + imm.hideSoftInputFromWindow(view.windowToken, InputMethodManager.HIDE_NOT_ALWAYS) + (view.context as? Activity)?.window?.let { window -> + WindowCompat.getInsetsController(window, view).hide(WindowInsetsCompat.Type.ime()) + } + focusManager.clearFocus(force = true) + } // Current offset: use drag offset during drag, animatable otherwise + optional enter slide val baseOffset = if (isDragging) dragOffset else offsetAnimatable.value @@ -333,6 +345,7 @@ fun SwipeBackContainer( var totalDragX = 0f var totalDragY = 0f var passedSlop = false + var keyboardHiddenForGesture = false // deferToChildren=true: pre-slop uses Main pass so children // (e.g. LazyRow) process first — if they consume, we back off. @@ -359,6 +372,14 @@ fun SwipeBackContainer( totalDragX += dragDelta.x totalDragY += dragDelta.y + if (!keyboardHiddenForGesture && + totalDragX > 10f && + kotlin.math.abs(totalDragX) > + kotlin.math.abs(totalDragY)) { + dismissKeyboard() + keyboardHiddenForGesture = true + } + if (!passedSlop) { // Child (e.g. LazyRow) already consumed — let it handle if (change.isConsumed) break @@ -393,17 +414,8 @@ fun SwipeBackContainer( screenWidthPx, active = true ) - - val imm = - context.getSystemService( - Context.INPUT_METHOD_SERVICE - ) as - InputMethodManager - imm.hideSoftInputFromWindow( - view.windowToken, - 0 - ) - focusManager.clearFocus() + dismissKeyboard() + keyboardHiddenForGesture = true change.consume() } else { @@ -489,6 +501,7 @@ fun SwipeBackContainer( shouldShow = false dragOffset = 0f clearSharedSwipeProgressIfOwner() + dismissKeyboard() onBack() } else { offsetAnimatable.animateTo(