Animated emoji support (#2064)
* Animated emoji support * Try to query preference only once * Revert to using SpannableStringBuilder
This commit is contained in:
parent
c685192d49
commit
9580870445
38 changed files with 225 additions and 120 deletions
|
|
@ -16,11 +16,9 @@
|
|||
@file:JvmName("CustomEmojiHelper")
|
||||
package com.keylesspalace.tusky.util
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.*
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.ReplacementSpan
|
||||
import android.view.View
|
||||
|
|
@ -33,6 +31,8 @@ import com.keylesspalace.tusky.entity.Emoji
|
|||
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.regex.Pattern
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.keylesspalace.tusky.settings.PrefKeys
|
||||
|
||||
/**
|
||||
* replaces emoji shortcodes in a text with EmojiSpans
|
||||
|
|
@ -41,7 +41,7 @@ import java.util.regex.Pattern
|
|||
* @param view a reference to the a view the emojis will be shown in (should be the TextView, but parents of the TextView are also acceptable)
|
||||
* @return the text with the shortcodes replaced by EmojiSpans
|
||||
*/
|
||||
fun CharSequence.emojify(emojis: List<Emoji>?, view: View) : CharSequence {
|
||||
fun CharSequence.emojify(emojis: List<Emoji>?, view: View, animate: Boolean) : CharSequence {
|
||||
if(emojis.isNullOrEmpty())
|
||||
return this
|
||||
|
||||
|
|
@ -56,9 +56,9 @@ fun CharSequence.emojify(emojis: List<Emoji>?, view: View) : CharSequence {
|
|||
|
||||
builder.setSpan(span, matcher.start(), matcher.end(), 0)
|
||||
Glide.with(view)
|
||||
.asBitmap()
|
||||
.asDrawable()
|
||||
.load(url)
|
||||
.into(span.getTarget())
|
||||
.into(span.getTarget(animate))
|
||||
}
|
||||
}
|
||||
return builder
|
||||
|
|
@ -97,11 +97,29 @@ class EmojiSpan(val viewWeakReference: WeakReference<View>) : ReplacementSpan()
|
|||
}
|
||||
}
|
||||
|
||||
fun getTarget(): Target<Bitmap> {
|
||||
return object : CustomTarget<Bitmap>() {
|
||||
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
||||
fun getTarget(animate : Boolean): Target<Drawable> {
|
||||
return object : CustomTarget<Drawable>() {
|
||||
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,5 +16,7 @@ data class StatusDisplayOptions(
|
|||
@get:JvmName("confirmReblogs")
|
||||
val confirmReblogs: Boolean,
|
||||
@get:JvmName("hideStats")
|
||||
val hideStats: Boolean
|
||||
val hideStats: Boolean,
|
||||
@get:JvmName("animateEmojis")
|
||||
val animateEmojis: Boolean
|
||||
)
|
||||
|
|
@ -243,7 +243,7 @@ class StatusViewHelper(private val itemView: View) {
|
|||
}
|
||||
}
|
||||
|
||||
fun setupPollReadonly(poll: PollViewData?, emojis: List<Emoji>, useAbsoluteTime: Boolean) {
|
||||
fun setupPollReadonly(poll: PollViewData?, emojis: List<Emoji>, statusDisplayOptions: StatusDisplayOptions) {
|
||||
val pollResults = listOf<TextView>(
|
||||
itemView.findViewById(R.id.status_poll_option_result_0),
|
||||
itemView.findViewById(R.id.status_poll_option_result_1),
|
||||
|
|
@ -261,10 +261,10 @@ class StatusViewHelper(private val itemView: View) {
|
|||
val timestamp = System.currentTimeMillis()
|
||||
|
||||
|
||||
setupPollResult(poll, emojis, pollResults)
|
||||
setupPollResult(poll, emojis, pollResults, statusDisplayOptions.animateEmojis)
|
||||
|
||||
pollDescription.visibility = View.VISIBLE
|
||||
pollDescription.text = getPollInfoText(timestamp, poll, pollDescription, useAbsoluteTime)
|
||||
pollDescription.text = getPollInfoText(timestamp, poll, pollDescription, statusDisplayOptions.useAbsoluteTime)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -292,7 +292,7 @@ class StatusViewHelper(private val itemView: View) {
|
|||
}
|
||||
|
||||
|
||||
private fun setupPollResult(poll: PollViewData, emojis: List<Emoji>, pollResults: List<TextView>) {
|
||||
private fun setupPollResult(poll: PollViewData, emojis: List<Emoji>, pollResults: List<TextView>, animateEmojis: Boolean) {
|
||||
val options = poll.options
|
||||
|
||||
for (i in 0 until Status.MAX_POLL_OPTIONS) {
|
||||
|
|
@ -300,7 +300,7 @@ class StatusViewHelper(private val itemView: View) {
|
|||
val percent = calculatePercent(options[i].votesCount, poll.votersCount, poll.votesCount)
|
||||
|
||||
val pollOptionText = buildDescription(options[i].title, percent, pollResults[i].context)
|
||||
pollResults[i].text = pollOptionText.emojify(emojis, pollResults[i])
|
||||
pollResults[i].text = pollOptionText.emojify(emojis, pollResults[i], animateEmojis)
|
||||
pollResults[i].visibility = View.VISIBLE
|
||||
|
||||
val level = percent * 100
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue