feat: Enhance Protocol with additional packet types and integrate AppleEmojiText for improved emoji display

This commit is contained in:
k1ngsterr1
2026-01-10 22:25:26 +05:00
parent 6014d23d69
commit 9baa7f444a
4 changed files with 105 additions and 5 deletions

View File

@@ -33,8 +33,8 @@ class AppleEmojiEditTextView @JvmOverloads constructor(
private var isUpdating = false
companion object {
// Regex для эмодзи
private val EMOJI_PATTERN = Pattern.compile(
// Regex для эмодзи - public для доступа из других компонентов
val EMOJI_PATTERN = Pattern.compile(
"[\\x{1F600}-\\x{1F64F}]|" + // Emoticons
"[\\x{1F300}-\\x{1F5FF}]|" + // Misc Symbols and Pictographs
"[\\x{1F680}-\\x{1F6FF}]|" + // Transport and Map
@@ -217,3 +217,93 @@ fun AppleEmojiTextField(
modifier = modifier
)
}
/**
* TextView с Apple эмодзи (для отображения, не редактирования)
*/
@Composable
fun AppleEmojiText(
text: String,
modifier: Modifier = Modifier,
color: androidx.compose.ui.graphics.Color = androidx.compose.ui.graphics.Color.White,
fontSize: androidx.compose.ui.unit.TextUnit = androidx.compose.ui.unit.TextUnit.Unspecified
) {
val fontSizeValue = if (fontSize == androidx.compose.ui.unit.TextUnit.Unspecified) 15f
else fontSize.value
AndroidView(
factory = { ctx ->
AppleEmojiTextView(ctx).apply {
setTextColor(color.toArgb())
setTextSize(fontSizeValue)
}
},
update = { view ->
view.setTextWithEmojis(text)
view.setTextColor(color.toArgb())
},
modifier = modifier
)
}
/**
* Apple Emoji TextView - для отображения текста с PNG эмодзи
*/
class AppleEmojiTextView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = android.R.attr.textViewStyle
) : android.widget.TextView(context, attrs, defStyleAttr) {
companion object {
private val EMOJI_PATTERN = AppleEmojiEditTextView.EMOJI_PATTERN
private val bitmapCache = LruCache<String, Bitmap>(100)
}
fun setTextWithEmojis(text: String) {
val spannable = SpannableStringBuilder(text)
val matcher = EMOJI_PATTERN.matcher(text)
while (matcher.find()) {
val emoji = matcher.group()
val unified = emojiToUnified(emoji)
val bitmap = loadEmojiBitmap(unified)
if (bitmap != null) {
val size = (textSize * 1.2).toInt()
val scaledBitmap = Bitmap.createScaledBitmap(bitmap, size, size, true)
val drawable = BitmapDrawable(resources, scaledBitmap)
drawable.setBounds(0, 0, size, size)
val span = ImageSpan(drawable, ImageSpan.ALIGN_BASELINE)
spannable.setSpan(span, matcher.start(), matcher.end(),
android.text.Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
}
setText(spannable)
}
private fun loadEmojiBitmap(unified: String): Bitmap? {
bitmapCache.get(unified)?.let { return it }
return try {
val path = "emoji/$unified.png"
val inputStream = context.assets.open(path)
val bitmap = BitmapFactory.decodeStream(inputStream)
inputStream.close()
bitmap?.let { bitmapCache.put(unified, it) }
bitmap
} catch (e: Exception) {
null
}
}
private fun emojiToUnified(emoji: String): String {
return emoji.codePoints()
.filter { it != 0xFE0F }
.mapToObj { String.format("%04x", it) }
.toList()
.joinToString("-")
}
}