Unverified Commit dd938089 authored by Filipe Brito's avatar Filipe Brito Committed by GitHub

Merge pull request #2017 from dev-ritik/issue_2009

[BUG] Fixes custom emoji alias rendering issue
parents e7fa51c0 1b91db74
...@@ -11,7 +11,7 @@ android { ...@@ -11,7 +11,7 @@ android {
minSdkVersion versions.minSdk minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk targetSdkVersion versions.targetSdk
versionCode 1 versionCode 1
versionName "0.1" versionName "1.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
javaCompileOptions { javaCompileOptions {
...@@ -40,6 +40,9 @@ dependencies { ...@@ -40,6 +40,9 @@ dependencies {
implementation libraries.androidKtx implementation libraries.androidKtx
implementation libraries.material implementation libraries.material
implementation libraries.glide
implementation libraries.timber
implementation libraries.room implementation libraries.room
kapt libraries.roomProcessor kapt libraries.roomProcessor
......
...@@ -7,15 +7,11 @@ import android.text.Spannable ...@@ -7,15 +7,11 @@ import android.text.Spannable
import android.text.SpannableString import android.text.SpannableString
import android.text.Spanned import android.text.Spanned
import android.text.style.ImageSpan import android.text.style.ImageSpan
import android.util.Log
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.gif.GifDrawable import com.bumptech.glide.load.resource.gif.GifDrawable
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import kotlinx.coroutines.Deferred import timber.log.Timber
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
class EmojiParser { class EmojiParser {
...@@ -31,7 +27,11 @@ class EmojiParser { ...@@ -31,7 +27,11 @@ class EmojiParser {
* @param factory Optional. A [Spannable.Factory] instance to reuse when creating [Spannable]. * @param factory Optional. A [Spannable.Factory] instance to reuse when creating [Spannable].
* @return A rendered Spannable containing any supported emoji. * @return A rendered Spannable containing any supported emoji.
*/ */
fun parse(context: Context, text: CharSequence, factory: Spannable.Factory? = null): CharSequence { fun parse(
context: Context,
text: CharSequence,
factory: Spannable.Factory? = null
): CharSequence {
val unicodedText = EmojiRepository.shortnameToUnicode(text) val unicodedText = EmojiRepository.shortnameToUnicode(text)
val spannable = factory?.newSpannable(unicodedText) val spannable = factory?.newSpannable(unicodedText)
?: SpannableString.valueOf(unicodedText) ?: SpannableString.valueOf(unicodedText)
...@@ -64,16 +64,20 @@ class EmojiParser { ...@@ -64,16 +64,20 @@ class EmojiParser {
inEmoji = true inEmoji = true
} else { } else {
if (inEmoji) { if (inEmoji) {
spannable.setSpan(EmojiTypefaceSpan("sans-serif", typeface), spannable.setSpan(
emojiStart, offset, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) EmojiTypefaceSpan("sans-serif", typeface),
emojiStart, offset, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
} }
inEmoji = false inEmoji = false
} }
offset += count offset += count
if (offset >= length && inEmoji) { if (offset >= length && inEmoji) {
spannable.setSpan(EmojiTypefaceSpan("sans-serif", typeface), spannable.setSpan(
emojiStart, offset, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) EmojiTypefaceSpan("sans-serif", typeface),
emojiStart, offset, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
} }
} }
...@@ -83,7 +87,7 @@ class EmojiParser { ...@@ -83,7 +87,7 @@ class EmojiParser {
return spannable.also { sp -> return spannable.also { sp ->
regex.findAll(spannable).iterator().forEach { match -> regex.findAll(spannable).iterator().forEach { match ->
customEmojis.find { it.shortname.toLowerCase() == match.value.toLowerCase() }?.let { emoji -> customEmojis.find { matchEmoji(it, match.value) }?.let { emoji ->
emoji.url?.let { url -> emoji.url?.let { url ->
try { try {
val glideRequest = if (url.endsWith("gif", true)) { val glideRequest = if (url.endsWith("gif", true)) {
...@@ -100,16 +104,25 @@ class EmojiParser { ...@@ -100,16 +104,25 @@ class EmojiParser {
val range = match.range val range = match.range
futureTarget.get()?.let { image -> futureTarget.get()?.let { image ->
if (image is Bitmap) { if (image is Bitmap) {
spannable.setSpan(ImageSpan(context, image), range.start, spannable.setSpan(
range.endInclusive + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ImageSpan(context, image), range.start,
range.endInclusive + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
} else if (image is GifDrawable) { } else if (image is GifDrawable) {
image.setBounds(0, 0, image.intrinsicWidth, image.intrinsicHeight) image.setBounds(
spannable.setSpan(ImageSpan(image), range.start, 0,
range.endInclusive + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) 0,
image.intrinsicWidth,
image.intrinsicHeight
)
spannable.setSpan(
ImageSpan(image), range.start,
range.endInclusive + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
} }
} }
} catch (ex: Throwable) { } catch (ex: Throwable) {
Log.e("EmojiParser", "", ex) Timber.e(ex)
} }
} }
} }
...@@ -117,12 +130,17 @@ class EmojiParser { ...@@ -117,12 +130,17 @@ class EmojiParser {
} }
} }
fun parseAsync( private fun matchEmoji(it: Emoji, text: String): Boolean {
context: Context, if (it.shortname == text) {
text: CharSequence, return true
factory: Spannable.Factory? = null } else {
): Deferred<CharSequence> { it.shortnameAlternates.forEach {
return GlobalScope.async(Dispatchers.IO) { parse(context, text, factory) } if (":$it:" == text) {
return true
}
}
return false
}
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment