feat: Refactor emoji picker behavior and improve animation performance

This commit is contained in:
2026-01-15 02:29:06 +05:00
parent 35e21fd3f6
commit c4043cd247
2 changed files with 121 additions and 52 deletions

View File

@@ -63,30 +63,30 @@ fun OptimizedEmojiPicker(
onClose: () -> Unit = {},
modifier: Modifier = Modifier
) {
// 🎭 Smooth animation для открытия/закрытия
// 🎭 Быстрая и плавная анимация (как в Telegram)
AnimatedVisibility(
visible = isVisible,
enter = slideInVertically(
initialOffsetY = { it },
animationSpec = tween(
durationMillis = 250,
durationMillis = 180, // 🔥 Быстрее!
easing = FastOutSlowInEasing
)
) + fadeIn(
animationSpec = tween(
durationMillis = 200,
durationMillis = 120,
easing = LinearEasing
)
),
exit = slideOutVertically(
targetOffsetY = { it },
animationSpec = tween(
durationMillis = 200,
durationMillis = 150, // 🔥 Быстрое закрытие
easing = FastOutLinearInEasing
)
) + fadeOut(
animationSpec = tween(
durationMillis = 150,
durationMillis = 100,
easing = LinearEasing
)
),
@@ -122,8 +122,15 @@ private fun EmojiPickerContent(
val gridState = rememberLazyGridState()
val scope = rememberCoroutineScope()
// 🚀 Загружаем эмодзи если еще не загружены
// 🚀 Отложенный рендеринг - даём анимации начаться без фриза
var shouldRenderContent by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
// Ждём 1 кадр чтобы анимация началась плавно
kotlinx.coroutines.delay(16) // ~1 frame at 60fps
shouldRenderContent = true
// Загружаем эмодзи если еще не загружены
if (!OptimizedEmojiCache.isLoaded) {
OptimizedEmojiCache.preload(context)
}
@@ -160,31 +167,45 @@ private fun EmojiPickerContent(
.height(350.dp) // Фиксированная высота как у клавиатуры
.background(panelBackground)
) {
// ============ КАТЕГОРИИ ============
CategoryBar(
categories = EMOJI_CATEGORIES,
selectedCategory = selectedCategory,
onCategorySelected = { selectedCategory = it },
isDarkTheme = isDarkTheme,
backgroundColor = categoryBarBackground
)
// ============ РАЗДЕЛИТЕЛЬ ============
Divider(
modifier = Modifier
.fillMaxWidth()
.height(0.5.dp),
color = dividerColor
)
// ============ СЕТКА ЭМОДЗИ ============
EmojiGrid(
isLoaded = OptimizedEmojiCache.isLoaded,
emojis = displayedEmojis,
gridState = gridState,
onEmojiSelected = onEmojiSelected,
isDarkTheme = isDarkTheme
)
// 🔥 Показываем пустую панель пока не готово
if (!shouldRenderContent) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator(
modifier = Modifier.size(24.dp),
color = PrimaryBlue,
strokeWidth = 2.dp
)
}
} else {
// ============ КАТЕГОРИИ ============
CategoryBar(
categories = EMOJI_CATEGORIES,
selectedCategory = selectedCategory,
onCategorySelected = { selectedCategory = it },
isDarkTheme = isDarkTheme,
backgroundColor = categoryBarBackground
)
// ============ РАЗДЕЛИТЕЛЬ ============
Divider(
modifier = Modifier
.fillMaxWidth()
.height(0.5.dp),
color = dividerColor
)
// ============ СЕТКА ЭМОДЗИ ============
EmojiGrid(
isLoaded = OptimizedEmojiCache.isLoaded,
emojis = displayedEmojis,
gridState = gridState,
onEmojiSelected = onEmojiSelected,
isDarkTheme = isDarkTheme
)
}
}
}