feat: Enhance AppleEmojiPicker to load all emojis from assets and group them by category

This commit is contained in:
k1ngsterr1
2026-01-12 02:59:16 +05:00
parent 7bac22850e
commit ec299bb415
3 changed files with 194 additions and 183 deletions

View File

@@ -9,7 +9,6 @@ import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.items
@@ -56,11 +55,8 @@ import com.rosetta.messenger.ui.components.VerifiedBadge
import com.rosetta.messenger.ui.onboarding.PrimaryBlue
import android.view.inputmethod.InputMethodManager
import android.content.Context
import android.graphics.Rect
import android.view.ViewTreeObserver
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.platform.LocalDensity
import java.text.SimpleDateFormat
import java.util.*
import kotlinx.coroutines.delay
@@ -176,10 +172,11 @@ fun ChatDetailScreen(
) {
val keyboardController = LocalSoftwareKeyboardController.current
val focusManager = LocalFocusManager.current
val backgroundColor = if (isDarkTheme) Color(0xFF0E0E0E) else Color(0xFFEFEFF3)
// Цвета как в React Native themes.ts
val backgroundColor = if (isDarkTheme) Color(0xFF1E1E1E) else Color(0xFFFFFFFF)
val textColor = if (isDarkTheme) Color.White else Color.Black
val secondaryTextColor = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666)
val inputBackgroundColor = if (isDarkTheme) Color(0xFF2A2A2A) else Color(0xFFF0F0F0)
val inputBackgroundColor = if (isDarkTheme) Color(0xFF2A2A2A) else Color(0xFFF2F3F5)
// <20> Fade-in анимация для всего экрана
var isVisible by remember { mutableStateOf(false) }
@@ -288,40 +285,13 @@ fun ChatDetailScreen(
// 🔥 Обработка системной кнопки назад
BackHandler { hideKeyboardAndBack() }
// 🔥 Ручное отслеживание высоты клавиатуры
val view = LocalView.current
val density = LocalDensity.current
var keyboardHeight by remember { mutableStateOf(0.dp) }
DisposableEffect(view) {
val listener = ViewTreeObserver.OnGlobalLayoutListener {
val rect = Rect()
view.getWindowVisibleDisplayFrame(rect)
val screenHeight = view.rootView.height
val keyboardHeightPx = screenHeight - rect.bottom
// Учитываем navigation bar (если клавиатура меньше 150px - это не клавиатура)
val actualKeyboardHeight = if (keyboardHeightPx > 150) keyboardHeightPx else 0
keyboardHeight = with(density) { actualKeyboardHeight.toDp() }
}
view.viewTreeObserver.addOnGlobalLayoutListener(listener)
// 🔥 Cleanup при выходе из экрана
DisposableEffect(Unit) {
onDispose {
view.viewTreeObserver.removeOnGlobalLayoutListener(listener)
focusManager.clearFocus()
keyboardController?.hide()
}
}
// Автоматический скролл вниз при появлении клавиатуры
LaunchedEffect(keyboardHeight) {
if (keyboardHeight > 0.dp && messages.isNotEmpty()) {
delay(50)
listState.animateScrollToItem(0)
}
}
// Инициализируем ViewModel с ключами и открываем диалог
LaunchedEffect(user.publicKey) {
@@ -354,7 +324,10 @@ fun ChatDetailScreen(
)
// 🚀 Весь контент с fade-in анимацией
Box(modifier = Modifier.fillMaxSize().graphicsLayer { alpha = screenAlpha }) {
Box(modifier = Modifier
.fillMaxSize()
.graphicsLayer { alpha = screenAlpha }
) {
// Telegram-style solid header background (без blur)
val headerBackground = if (isDarkTheme) Color(0xFF212121) else Color(0xFFFFFFFF)
@@ -577,23 +550,17 @@ fun ChatDetailScreen(
)
}
},
containerColor = Color.Transparent
containerColor = backgroundColor // Фон всего чата
) { paddingValues ->
// 🔥 Box с фиксированным Input внизу и сообщениями выше
Box(
// 🔥 Простой Column - сообщения сверху, инпут снизу
// Клавиатура сама поднимает контент через adjustResize
Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
// Список сообщений - занимает всё пространство, с padding снизу для input и клавиатуры
val inputBarHeight = 60.dp
val bottomPadding = inputBarHeight + keyboardHeight
Box(
modifier = Modifier
.fillMaxSize()
.padding(bottom = bottomPadding)
) {
// Список сообщений - занимает всё доступное пространство
Box(modifier = Modifier.weight(1f).fillMaxWidth()) {
if (messages.isEmpty()) {
// Пустое состояние
Column(
@@ -759,42 +726,35 @@ fun ChatDetailScreen(
)
}
}
} // Закрытие внутреннего Box для сообщений
// 🔥 INPUT BAR - фиксированный элемент внизу экрана
Box(
modifier = Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth()
.padding(bottom = keyboardHeight) // Ручной padding над клавиатурой
) {
MessageInputBar(
value = inputText,
onValueChange = {
viewModel.updateInputText(it)
// Отправляем индикатор печатания
if (it.isNotEmpty() && !isSavedMessages) {
viewModel.sendTypingIndicator()
}
},
onSend = {
// Скрываем кнопку scroll на время отправки
isSendingMessage = true
viewModel.sendMessage()
// Скроллим к новому сообщению
scope.launch {
delay(100)
listState.animateScrollToItem(0)
delay(300) // Ждём завершения анимации
isSendingMessage = false
}
},
isDarkTheme = isDarkTheme,
backgroundColor = inputBackgroundColor,
textColor = textColor,
placeholderColor = secondaryTextColor
)
}
// 🔥 INPUT BAR - обычный элемент внизу Column
MessageInputBar(
value = inputText,
onValueChange = {
viewModel.updateInputText(it)
// Отправляем индикатор печатания
if (it.isNotEmpty() && !isSavedMessages) {
viewModel.sendTypingIndicator()
}
},
onSend = {
// Скрываем кнопку scroll на время отправки
isSendingMessage = true
viewModel.sendMessage()
// Скроллим к новому сообщению
scope.launch {
delay(100)
listState.animateScrollToItem(0)
delay(300) // Ждём завершения анимации
isSendingMessage = false
}
},
isDarkTheme = isDarkTheme,
backgroundColor = inputBackgroundColor,
textColor = textColor,
placeholderColor = secondaryTextColor
)
}
}
} // Закрытие Box с fade-in
@@ -1148,10 +1108,7 @@ private fun MessageInputBar(
}
Column(
modifier =
Modifier.fillMaxWidth()
.background(Color.Transparent)
// imePadding уже на родительском Column
modifier = Modifier.fillMaxWidth()
) {
// 🔥 TELEGRAM-STYLE FLOATING LIQUID GLASS INPUT
Row(
@@ -1344,9 +1301,5 @@ private fun MessageInputBar(
onClose = { showEmojiPicker = false }
)
}
if (!showEmojiPicker) {
Spacer(modifier = Modifier.navigationBarsPadding())
}
}
}