diff --git a/app/src/main/java/app/rosette/android/ui/keyboard/AnimatedKeyboardTransition.kt b/app/src/main/java/app/rosette/android/ui/keyboard/AnimatedKeyboardTransition.kt index 9b240b0..4e80546 100644 --- a/app/src/main/java/app/rosette/android/ui/keyboard/AnimatedKeyboardTransition.kt +++ b/app/src/main/java/app/rosette/android/ui/keyboard/AnimatedKeyboardTransition.kt @@ -7,14 +7,16 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.unit.dp import android.util.Log +import kotlinx.coroutines.delay /** * 🚀 Telegram-style: Fixed Height Box + Fade In/Out @@ -36,25 +38,30 @@ fun AnimatedKeyboardTransition( val tag = "AnimatedTransition" // 🔥 Отслеживаем был ли emoji открыт (для определения перехода emoji→keyboard) - val wasEmojiShown = remember { mutableStateOf(false) } - val isTransitioningToKeyboard = remember { mutableStateOf(false) } + var wasEmojiShown by remember { mutableStateOf(false) } + var isTransitioningToKeyboard by remember { mutableStateOf(false) } - // Когда emoji открывается - запоминаем - LaunchedEffect(showEmojiPicker) { - if (showEmojiPicker) { - wasEmojiShown.value = true - } else if (wasEmojiShown.value) { - // Emoji закрылся после того как был открыт = переход emoji→keyboard - isTransitioningToKeyboard.value = true - } + // 🔥 Клавиатура достигла ПОЛНОЙ высоты (разница не более 3dp) + val isKeyboardFullHeight = coordinator.emojiHeight > 0.dp && + coordinator.keyboardHeight >= coordinator.emojiHeight - 3.dp + + // Логика перехода + if (showEmojiPicker && !wasEmojiShown) { + wasEmojiShown = true + } + if (!showEmojiPicker && wasEmojiShown && !isTransitioningToKeyboard) { + // Emoji закрылся после того как был открыт = переход emoji→keyboard + isTransitioningToKeyboard = true } - // Сбрасываем флаг перехода когда клавиатура достигла полной высоты - val isKeyboardFullHeight = coordinator.keyboardHeight >= coordinator.emojiHeight * 0.95f && coordinator.emojiHeight > 0.dp - LaunchedEffect(isKeyboardFullHeight) { - if (isKeyboardFullHeight && isTransitioningToKeyboard.value) { - isTransitioningToKeyboard.value = false - wasEmojiShown.value = false + // 🔥 КЛЮЧЕВОЕ: Сбрасываем флаг ПОСЛЕ небольшой задержки когда клавиатура полностью открылась + // Это гарантирует что Box останется виден пока система не отрисует клавиатуру + LaunchedEffect(isKeyboardFullHeight, isTransitioningToKeyboard) { + if (isKeyboardFullHeight && isTransitioningToKeyboard) { + delay(50) // Небольшая задержка для завершения отрисовки + isTransitioningToKeyboard = false + wasEmojiShown = false + Log.d("AnimatedTransition", "✅ Transition complete, keyboard at full height") } } @@ -73,15 +80,13 @@ fun AnimatedKeyboardTransition( // 🔥 Box показан когда: // 1. showEmojiPicker=true (emoji открыт), ИЛИ - // 2. анимация fade-out ещё идёт (alpha > 0.01), ИЛИ - // 3. переход emoji→keyboard И клавиатура ещё не достигла полной высоты - val isFadingOut = !showEmojiPicker && animatedAlpha > 0.01f - val shouldShowBox = showEmojiPicker || isFadingOut || isTransitioningToKeyboard.value + // 2. переход emoji→keyboard активен (ждём пока клавиатура полностью откроется) + val shouldShowBox = showEmojiPicker || isTransitioningToKeyboard // 🔥 ВАЖНО: Обновляем состояние в координаторе для отключения imePadding coordinator.isEmojiBoxVisible = shouldShowBox - Log.d(tag, "🎨 Emoji panel: show=$showEmojiPicker, alpha=$animatedAlpha, shouldShow=$shouldShowBox, transitioning=${isTransitioningToKeyboard.value}, kbHeight=${coordinator.keyboardHeight}") + Log.d(tag, "🎨 Emoji panel: show=$showEmojiPicker, alpha=$animatedAlpha, shouldShow=$shouldShowBox, transitioning=$isTransitioningToKeyboard, kbHeight=${coordinator.keyboardHeight}, emojiH=${coordinator.emojiHeight}") if (shouldShowBox) { Box( diff --git a/app/src/main/java/com/rosetta/messenger/ui/chats/ChatDetailScreen.kt b/app/src/main/java/com/rosetta/messenger/ui/chats/ChatDetailScreen.kt index c9feab4..ed7bafe 100644 --- a/app/src/main/java/com/rosetta/messenger/ui/chats/ChatDetailScreen.kt +++ b/app/src/main/java/com/rosetta/messenger/ui/chats/ChatDetailScreen.kt @@ -2233,14 +2233,17 @@ private fun MessageInputBar( ) ) + // 🔥 Когда emoji Box виден ИЛИ клавиатура открыта - НЕ добавляем navigation bar padding + val shouldAddNavBarPadding = !isKeyboardVisible && !coordinator.isEmojiBoxVisible + Column( modifier = Modifier .fillMaxWidth() .background( color = backgroundColor // Тот же цвет что и фон чата ) - .padding(bottom = if (isKeyboardVisible) 0.dp else 16.dp) - .navigationBarsPadding() // 🔥 Учитываем navigation bar когда клавиатура закрыта + .padding(bottom = if (isKeyboardVisible || coordinator.isEmojiBoxVisible) 0.dp else 16.dp) + .then(if (shouldAddNavBarPadding) Modifier.navigationBarsPadding() else Modifier) ) { // REPLY PANEL AnimatedVisibility(