Animated emoji support
This commit is contained in:
parent
5e9e626012
commit
2eba3f41ba
|
@ -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>
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue