EmojiReactionsAdapter: implement custom emoji reactions on messages
Signed-off-by: Hélène <pleroma-dev@helene.moe> Signed-off-by: Adolfo Santiago <epoch@nixnetmail.com>
This commit is contained in:
parent
8da35a37c1
commit
e6b402b377
2 changed files with 57 additions and 23 deletions
|
@ -4,11 +4,14 @@ import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.Spanned;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.TextView.BufferType;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
@ -21,6 +24,7 @@ import com.keylesspalace.tusky.entity.Status;
|
||||||
import com.keylesspalace.tusky.entity.EmojiReaction;
|
import com.keylesspalace.tusky.entity.EmojiReaction;
|
||||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||||
import com.keylesspalace.tusky.util.CardViewMode;
|
import com.keylesspalace.tusky.util.CardViewMode;
|
||||||
|
import com.keylesspalace.tusky.util.CustomEmojiHelper;
|
||||||
import com.keylesspalace.tusky.util.LinkHelper;
|
import com.keylesspalace.tusky.util.LinkHelper;
|
||||||
import com.keylesspalace.tusky.util.StatusDisplayOptions;
|
import com.keylesspalace.tusky.util.StatusDisplayOptions;
|
||||||
import com.keylesspalace.tusky.viewdata.StatusViewData;
|
import com.keylesspalace.tusky.viewdata.StatusViewData;
|
||||||
|
@ -51,12 +55,20 @@ public class EmojiReactionsAdapter extends RecyclerView.Adapter<SingleViewHolder
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(SingleViewHolder holder, int position) {
|
public void onBindViewHolder(SingleViewHolder holder, int position) {
|
||||||
EmojiReaction reaction = reactions.get(position);
|
EmojiReaction reaction = reactions.get(position);
|
||||||
String str = reaction.getName() + " " + reaction.getCount();
|
SpannableStringBuilder builder = new SpannableStringBuilder(
|
||||||
|
reaction.getName() + " " + reaction.getCount());
|
||||||
|
|
||||||
// no custom emoji yet!
|
|
||||||
EmojiAppCompatButton btn = (EmojiAppCompatButton)holder.itemView;
|
EmojiAppCompatButton btn = (EmojiAppCompatButton)holder.itemView;
|
||||||
|
|
||||||
btn.setText(str);
|
var url = reaction.getUrl();
|
||||||
|
if (url != null) {
|
||||||
|
var span = CustomEmojiHelper.createEmojiSpan(url, btn, true);
|
||||||
|
|
||||||
|
builder.setSpan(span, 0, reaction.getName().length(),
|
||||||
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.setText(builder, BufferType.SPANNABLE);
|
||||||
btn.setActivated(reaction.getMe());
|
btn.setActivated(reaction.getMe());
|
||||||
btn.setOnClickListener(v -> {
|
btn.setOnClickListener(v -> {
|
||||||
listener.onEmojiReactMenu(v, reaction, statusId);
|
listener.onEmojiReactMenu(v, reaction, statusId);
|
||||||
|
|
|
@ -70,25 +70,8 @@ fun CharSequence.emojify(
|
||||||
.matcher(this)
|
.matcher(this)
|
||||||
|
|
||||||
while(matcher.find()) {
|
while(matcher.find()) {
|
||||||
val span = if(smallEmojis) {
|
val span = createEmojiSpan(url, view, smallEmojis, animate)
|
||||||
SmallEmojiSpan(WeakReference<View>(view))
|
|
||||||
} else {
|
|
||||||
EmojiSpan(WeakReference<View>(view))
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.setSpan(span, matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
builder.setSpan(span, matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
|
||||||
var glideRequest = Glide.with(view).load(url)
|
|
||||||
.set(AnimationDecoderOption.DISABLE_ANIMATION_GIF_DECODER, !animate)
|
|
||||||
.set(AnimationDecoderOption.DISABLE_ANIMATION_WEBP_DECODER, !animate)
|
|
||||||
.set(AnimationDecoderOption.DISABLE_ANIMATION_APNG_DECODER, !animate)
|
|
||||||
val mimetype = getMimeType(url)
|
|
||||||
if(mimetype == MIME.SVG) {
|
|
||||||
glideRequest = glideRequest
|
|
||||||
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
|
|
||||||
.override(512, 512)
|
|
||||||
}
|
|
||||||
glideRequest.into(span.getTarget(animate))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +82,45 @@ fun CharSequence.emojify(emojis: List<Emoji>?, view: View): CharSequence {
|
||||||
return this.emojify(emojis, view, false)
|
return this.emojify(emojis, view, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createEmojiSpan(
|
||||||
|
emoji_url: String,
|
||||||
|
view: View,
|
||||||
|
forceSmallEmoji: Boolean = false
|
||||||
|
): EmojiSpan {
|
||||||
|
val pm = PreferenceManager.getDefaultSharedPreferences(view.context)
|
||||||
|
val smallEmojis = forceSmallEmoji || !pm.getBoolean(PrefKeys.BIG_EMOJIS, true)
|
||||||
|
val animate = pm.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
|
||||||
|
|
||||||
|
return createEmojiSpan(emoji_url, view, smallEmojis, animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createEmojiSpan(
|
||||||
|
emoji_url: String,
|
||||||
|
view: View,
|
||||||
|
smallEmojis: Boolean = false,
|
||||||
|
animate: Boolean = false
|
||||||
|
): EmojiSpan {
|
||||||
|
val span = if(smallEmojis) {
|
||||||
|
SmallEmojiSpan(WeakReference<View>(view))
|
||||||
|
} else {
|
||||||
|
EmojiSpan(WeakReference<View>(view))
|
||||||
|
}
|
||||||
|
|
||||||
|
var glideRequest = Glide.with(view).load(emoji_url)
|
||||||
|
.set(AnimationDecoderOption.DISABLE_ANIMATION_GIF_DECODER, !animate)
|
||||||
|
.set(AnimationDecoderOption.DISABLE_ANIMATION_WEBP_DECODER, !animate)
|
||||||
|
.set(AnimationDecoderOption.DISABLE_ANIMATION_APNG_DECODER, !animate)
|
||||||
|
val mimetype = getMimeType(emoji_url)
|
||||||
|
if(mimetype == MIME.SVG) {
|
||||||
|
glideRequest = glideRequest
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
|
||||||
|
.override(512, 512)
|
||||||
|
}
|
||||||
|
glideRequest.into(span.getTarget(animate))
|
||||||
|
|
||||||
|
return span;
|
||||||
|
}
|
||||||
|
|
||||||
open class EmojiSpan(val viewWeakReference: WeakReference<View>) : ReplacementSpan() {
|
open class EmojiSpan(val viewWeakReference: WeakReference<View>) : ReplacementSpan() {
|
||||||
var imageDrawable: Drawable? = null
|
var imageDrawable: Drawable? = null
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue