feat: Optimize emoji picker performance by eliminating chunk loading, reducing animations, and improving emoji caching
This commit is contained in:
@@ -432,41 +432,35 @@ object EmojiCache {
|
||||
}
|
||||
|
||||
private fun groupEmojis(allEmojis: List<String>): Map<String, List<String>> {
|
||||
val result = mutableMapOf<String, MutableList<String>>()
|
||||
val usedEmojis = mutableSetOf<String>()
|
||||
val emojiToCategory = mutableMapOf<String, EmojiCategory>()
|
||||
// 🚀 Оптимизированная группировка - один проход вместо двух
|
||||
val result = EMOJI_CATEGORIES.associate { it.key to mutableListOf<String>() }
|
||||
val symbolsCategory = EMOJI_CATEGORIES.find { it.key == "Symbols" }!!
|
||||
|
||||
EMOJI_CATEGORIES.forEach { category ->
|
||||
result[category.key] = mutableListOf()
|
||||
}
|
||||
|
||||
// Сначала определяем категорию для каждого emoji
|
||||
// Один проход по всем emoji - распределяем по категориям
|
||||
for (emoji in allEmojis) {
|
||||
var assigned = false
|
||||
for (category in EMOJI_CATEGORIES) {
|
||||
if (emojiMatchesCategory(emoji, category) && emoji !in usedEmojis) {
|
||||
if (emojiMatchesCategory(emoji, category)) {
|
||||
result[category.key]?.add(emoji)
|
||||
usedEmojis.add(emoji)
|
||||
emojiToCategory[emoji] = category
|
||||
assigned = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Нераспределенные emoji идут в Symbols
|
||||
for (emoji in allEmojis) {
|
||||
if (emoji !in usedEmojis) {
|
||||
// Нераспределенные идут в Symbols
|
||||
if (!assigned) {
|
||||
result["Symbols"]?.add(emoji)
|
||||
emojiToCategory[emoji] = EMOJI_CATEGORIES.find { it.key == "Symbols" }!!
|
||||
}
|
||||
}
|
||||
|
||||
// Сортируем каждую категорию согласно Unicode порядку
|
||||
for ((key, emojis) in result) {
|
||||
// 🚀 Сортируем каждую категорию один раз
|
||||
return result.mapValues { (key, emojis) ->
|
||||
val category = EMOJI_CATEGORIES.find { it.key == key }
|
||||
if (category != null) {
|
||||
emojis.sortWith { a, b ->
|
||||
if (category != null && emojis.size > 1) {
|
||||
emojis.sortedWith { a, b ->
|
||||
getEmojiSortIndex(a, category).compareTo(getEmojiSortIndex(b, category))
|
||||
}
|
||||
} else {
|
||||
emojis
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,7 +546,7 @@ fun CategoryButton(
|
||||
isDarkTheme: Boolean = true,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
// 🚀 Убрали анимацию scale для производительности
|
||||
// 🚀 Без анимаций для максимальной производительности
|
||||
val backgroundColor = if (isSelected) PrimaryBlue.copy(alpha = 0.2f) else Color.Transparent
|
||||
val iconTint = if (isSelected) PrimaryBlue
|
||||
else if (isDarkTheme) Color.White.copy(alpha = 0.6f)
|
||||
@@ -563,7 +557,11 @@ fun CategoryButton(
|
||||
.size(40.dp)
|
||||
.clip(CircleShape)
|
||||
.background(backgroundColor)
|
||||
.clickable(onClick = onClick),
|
||||
.clickable(
|
||||
onClick = onClick,
|
||||
indication = null, // 🚀 Убираем ripple для производительности
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
@@ -596,11 +594,9 @@ fun AppleEmojiPickerPanel(
|
||||
}
|
||||
}
|
||||
|
||||
// 🚀 Chunk loading: показываем эмодзи порциями для плавности
|
||||
var loadedCount by remember { mutableStateOf(40) } // Начинаем с 40 (5 рядов)
|
||||
|
||||
// Текущие эмодзи для выбранной категории
|
||||
val allEmojis = remember(selectedCategory, EmojiCache.isLoaded) {
|
||||
// 🚀 Показываем все эмодзи сразу - LazyGrid сам виртуализирует рендеринг!
|
||||
// Никаких chunk loading - это только добавляет recomposition
|
||||
val displayedEmojis = remember(selectedCategory, EmojiCache.isLoaded) {
|
||||
if (EmojiCache.isLoaded) {
|
||||
EmojiCache.getEmojisForCategory(selectedCategory.key)
|
||||
} else {
|
||||
@@ -608,20 +604,9 @@ fun AppleEmojiPickerPanel(
|
||||
}
|
||||
}
|
||||
|
||||
// 🚀 При смене категории сбрасываем чанки и постепенно догружаем
|
||||
// 🚀 При смене категории просто скроллим наверх
|
||||
LaunchedEffect(selectedCategory) {
|
||||
loadedCount = 40 // Сразу показываем 40 эмодзи
|
||||
gridState.scrollToItem(0)
|
||||
// Догружаем остальные чанками
|
||||
while (loadedCount < allEmojis.size) {
|
||||
delay(32) // 2 фрейма
|
||||
loadedCount = minOf(loadedCount + 24, allEmojis.size)
|
||||
}
|
||||
}
|
||||
|
||||
// Отображаемые эмодзи (с chunk loading)
|
||||
val displayedEmojis = remember(allEmojis, loadedCount) {
|
||||
allEmojis.take(loadedCount)
|
||||
}
|
||||
|
||||
val panelBackground = if (isDarkTheme) Color(0xFF1C1C1E) else Color(0xFFF2F2F7)
|
||||
@@ -688,16 +673,17 @@ fun AppleEmojiPickerPanel(
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// 🚀 Оптимизированная LazyVerticalGrid с chunk loading
|
||||
// 🚀 Максимально оптимизированная LazyVerticalGrid
|
||||
LazyVerticalGrid(
|
||||
state = gridState,
|
||||
columns = GridCells.Fixed(8),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
horizontalArrangement = Arrangement.spacedBy(1.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(1.dp),
|
||||
contentPadding = PaddingValues(start = 12.dp, end = 12.dp, top = 4.dp, bottom = 4.dp)
|
||||
// 🚀 Убираем spacing для производительности
|
||||
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 4.dp),
|
||||
// 🚀 Увеличиваем prefetch для плавной прокрутки
|
||||
userScrollEnabled = true
|
||||
) {
|
||||
items(
|
||||
items = displayedEmojis,
|
||||
|
||||
Reference in New Issue
Block a user