Animated emoji support

This commit is contained in:
Alibek Omarov 2020-10-19 02:50:24 +03:00
parent 5e9e626012
commit 2eba3f41ba
4 changed files with 38 additions and 14 deletions

View File

@ -47,6 +47,7 @@
<string name="pref_title_hide_muted_users">Hide muted users</string> <string name="pref_title_hide_muted_users">Hide muted users</string>
<string name="pref_title_enable_big_emojis">Enable bigger custom emojis</string> <string name="pref_title_enable_big_emojis">Enable bigger custom emojis</string>
<string name="pref_title_enable_experimental_stickers">Enable experimental Pleroma-FE stickers(if available)</string> <string name="pref_title_enable_experimental_stickers">Enable experimental Pleroma-FE stickers(if available)</string>
<string name="pref_title_animate_custom_emojis">Animate custom emojis</string>
<string name="attachment_type_image">Image</string> <string name="attachment_type_image">Image</string>
<string name="attachment_type_video">Video</string> <string name="attachment_type_video">Video</string>

View File

@ -169,7 +169,7 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable {
setDefaultValue(false) setDefaultValue(false)
key = PrefKeys.HIDE_MUTED_USERS key = PrefKeys.HIDE_MUTED_USERS
setTitle(R.string.pref_title_hide_muted_users) setTitle(R.string.pref_title_hide_muted_users)
isSingleLineTitle = true isSingleLineTitle = false
} }
switchPreference { switchPreference {
@ -192,6 +192,13 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable {
setTitle(R.string.pref_title_enable_experimental_stickers) setTitle(R.string.pref_title_enable_experimental_stickers)
isSingleLineTitle = false isSingleLineTitle = false
} }
switchPreference {
setDefaultValue(false)
key = PrefKeys.ANIMATE_CUSTOM_EMOJIS
setTitle(R.string.pref_title_animate_custom_emojis)
isSingleLineTitle = false
}
} }
preferenceCategory(R.string.pref_title_privacy) { preferenceCategory(R.string.pref_title_privacy) {

View File

@ -35,6 +35,7 @@ object PrefKeys {
const val STICKERS = "stickers" const val STICKERS = "stickers"
const val ANONYMIZE_FILENAMES = "anonymizeFilenames" const val ANONYMIZE_FILENAMES = "anonymizeFilenames"
const val HIDE_MUTED_USERS = "hideMutedUsers" const val HIDE_MUTED_USERS = "hideMutedUsers"
const val ANIMATE_CUSTOM_EMOJIS = "animateCustomEmojis"
const val CUSTOM_TABS = "customTabs" const val CUSTOM_TABS = "customTabs"

View File

@ -16,17 +16,13 @@
@file:JvmName("CustomEmojiHelper") @file:JvmName("CustomEmojiHelper")
package com.keylesspalace.tusky.util package com.keylesspalace.tusky.util
import android.graphics.Bitmap
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Paint import android.graphics.Paint
import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.*
import android.graphics.drawable.Drawable
import android.text.SpannableString import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned import android.text.Spanned
import android.text.style.ReplacementSpan import android.text.style.ReplacementSpan
import android.view.View import android.view.View
import androidx.core.text.toSpannable
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget import com.bumptech.glide.request.target.CustomTarget
@ -37,6 +33,7 @@ import com.keylesspalace.tusky.entity.Emoji
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.regex.Pattern import java.util.regex.Pattern
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.keylesspalace.tusky.settings.PrefKeys
/** /**
* replaces emoji shortcodes in a text with EmojiSpans * replaces emoji shortcodes in a text with EmojiSpans
@ -51,8 +48,8 @@ fun CharSequence.emojify(emojis: List<Emoji>?, view: View, forceSmallEmoji: Bool
val builder = SpannableString.valueOf(this) val builder = SpannableString.valueOf(this)
val pm = PreferenceManager.getDefaultSharedPreferences(view.context) val pm = PreferenceManager.getDefaultSharedPreferences(view.context)
val smallEmojis = forceSmallEmoji || !pm.getBoolean("bigEmojis", true) val smallEmojis = forceSmallEmoji || !pm.getBoolean(PrefKeys.BIG_EMOJIS, true)
// val animatedEmojis = pm.getBoolean("animateEmojis", false) val animate = pm.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
emojis.forEach { (shortcode, url) -> emojis.forEach { (shortcode, url) ->
val matcher = Pattern.compile(":$shortcode:", Pattern.LITERAL) val matcher = Pattern.compile(":$shortcode:", Pattern.LITERAL)
@ -67,9 +64,9 @@ fun CharSequence.emojify(emojis: List<Emoji>?, view: View, forceSmallEmoji: Bool
builder.setSpan(span, matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); builder.setSpan(span, matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Glide.with(view) Glide.with(view)
.asBitmap() .asDrawable()
.load(url) .load(url)
.into(span.getTarget()) .into(span.getTarget(animate))
} }
} }
return builder return builder
@ -112,11 +109,29 @@ open class EmojiSpan(val viewWeakReference: WeakReference<View>) : ReplacementSp
} }
} }
fun getTarget(): Target<Bitmap> { fun getTarget(animate : Boolean): Target<Drawable> {
return object : CustomTarget<Bitmap>() { return object : CustomTarget<Drawable>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) { override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
viewWeakReference.get()?.let { view -> viewWeakReference.get()?.let { view ->
imageDrawable = BitmapDrawable(view.context.resources, resource) if(animate && resource is Animatable) {
val callback = resource.callback
resource.callback = object: Drawable.Callback {
override fun unscheduleDrawable(p0: Drawable, p1: Runnable) {
callback?.unscheduleDrawable(p0, p1)
}
override fun scheduleDrawable(p0: Drawable, p1: Runnable, p2: Long) {
callback?.scheduleDrawable(p0, p1, p2)
}
override fun invalidateDrawable(p0: Drawable) {
callback?.invalidateDrawable(p0)
view.invalidate()
}
}
resource.start()
}
imageDrawable = resource
view.invalidate() view.invalidate()
} }
} }