Commit 2cb08046 authored by Thomas's avatar Thomas
Browse files

Fix issue #288 - Custom Emoji not always displayed

parent ffb6596c
Loading
Loading
Loading
Loading
+22 −6
Original line number Diff line number Diff line
@@ -115,6 +115,10 @@ public class Status implements Serializable, Cloneable {
    public transient boolean submitted = false;
    public transient boolean spoilerChecked = false;
    public Filter filteredByApp;
    public transient Spannable contentSpan;
    public transient Spannable contentSpoilerSpan;
    public transient Spannable contentTranslateSpan;

    @Override
    public boolean equals(@Nullable Object obj) {
        boolean same = false;
@@ -124,17 +128,29 @@ public class Status implements Serializable, Cloneable {
        return same;
    }

    public synchronized Spannable getSpanContent(Context context, WeakReference<View> viewWeakReference) {
        return SpannableHelper.convert(context, content, this, null, null, true, viewWeakReference);
    public synchronized Spannable getSpanContent(Context context, WeakReference<View> viewWeakReference, Callback callback) {
        if (contentSpan == null) {
            contentSpan = SpannableHelper.convert(context, content, this, null, null, true, viewWeakReference, callback);
        }
        return contentSpan;
    }

    public synchronized Spannable getSpanSpoiler(Context context, WeakReference<View> viewWeakReference, Callback callback) {
        if (contentSpoilerSpan == null) {
            contentSpoilerSpan = SpannableHelper.convert(context, spoiler_text, this, null, null, true, viewWeakReference, callback);
        }
        return contentSpoilerSpan;
    }

    public synchronized Spannable getSpanSpoiler(Context context, WeakReference<View> viewWeakReference) {
        return SpannableHelper.convert(context, spoiler_text, this, null, null, true, viewWeakReference);
    public synchronized Spannable getSpanTranslate(Context context, WeakReference<View> viewWeakReference, Callback callback) {
        if (contentTranslateSpan == null) {
            contentTranslateSpan = SpannableHelper.convert(context, translationContent, this, null, null, true, viewWeakReference, callback);
        }
        return contentTranslateSpan;
    }

    public synchronized Spannable getSpanTranslate(Context context, WeakReference<View> viewWeakReference) {
        return SpannableHelper.convert(context, translationContent, this, null, null, true, viewWeakReference);
    public interface Callback {
        void emojiFetched();
    }

    @NonNull
+34 −2
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.text.SpannableStringBuilder;
import android.text.style.ReplacementSpan;
import android.view.View;

@@ -13,26 +14,53 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceManager;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;

import java.lang.ref.WeakReference;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import app.fedilab.android.R;
import app.fedilab.android.client.entities.api.Emoji;
import app.fedilab.android.client.entities.api.Status;


public class CustomEmoji extends ReplacementSpan {
    private final float scale;
    private final WeakReference<View> viewWeakReference;
    private Drawable imageDrawable;

    private boolean callbackCalled;

    CustomEmoji(WeakReference<View> viewWeakReference) {
        Context mContext = viewWeakReference.get().getContext();
        this.viewWeakReference = viewWeakReference;
        SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
        scale = sharedpreferences.getFloat(mContext.getString(R.string.SET_FONT_SCALE), 1.1f);
        callbackCalled = false;
    }

    public SpannableStringBuilder makeEmoji(SpannableStringBuilder content, List<Emoji> emojiList, boolean animate, Status.Callback callback) {
        if (emojiList != null && emojiList.size() > 0) {
            int count = 1;
            for (Emoji emoji : emojiList) {
                Matcher matcher = Pattern.compile(":" + emoji.shortcode + ":", Pattern.LITERAL)
                        .matcher(content);
                while (matcher.find()) {
                    CustomEmoji customEmoji = new CustomEmoji(new WeakReference<>(viewWeakReference.get()));
                    content.setSpan(customEmoji, matcher.start(), matcher.end(), 0);
                    Glide.with(viewWeakReference.get())
                            .asDrawable()
                            .load(animate ? emoji.url : emoji.static_url)
                            .into(customEmoji.getTarget(animate, count == emojiList.size() && !callbackCalled ? callback : null));
                }
                count++;
            }
        }
        return content;
    }

    @Override
@@ -61,7 +89,7 @@ public class CustomEmoji extends ReplacementSpan {
        }
    }

    public Target<Drawable> getTarget(boolean animate) {
    public Target<Drawable> getTarget(boolean animate, Status.Callback callback) {
        return new CustomTarget<Drawable>() {
            @Override
            public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
@@ -97,6 +125,10 @@ public class CustomEmoji extends ReplacementSpan {
                if (view != null) {
                    view.invalidate();
                }
                if (callback != null) {
                    callbackCalled = true;
                    callback.emojiFetched();
                }
            }

            @Override
+11 −18
Original line number Diff line number Diff line
@@ -89,10 +89,16 @@ public class SpannableHelper {

    public static final String CLICKABLE_SPAN = "CLICKABLE_SPAN";

    public static Spannable convert(Context context, String text,
                                    Status status, Account account, Announcement announcement,
                                    boolean convertHtml, WeakReference<View> viewWeakReference) {
        return convert(context, text, status, account, announcement, convertHtml, viewWeakReference, null);
    }

    public static Spannable convert(Context context, String text,
                                    Status status, Account account, Announcement announcement,
                                    boolean convertHtml,
                                    WeakReference<View> viewWeakReference) {
                                    WeakReference<View> viewWeakReference, Status.Callback callback) {


        SpannableString initialContent;
@@ -161,20 +167,8 @@ public class SpannableHelper {
        }
        SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
        boolean animate = !sharedpreferences.getBoolean(context.getString(R.string.SET_DISABLE_ANIMATED_EMOJI), false);
        if (emojiList != null && emojiList.size() > 0) {
            for (Emoji emoji : emojiList) {
                Matcher matcher = Pattern.compile(":" + emoji.shortcode + ":", Pattern.LITERAL)
                        .matcher(content);
                while (matcher.find()) {
        CustomEmoji customEmoji = new CustomEmoji(new WeakReference<>(view));
                    content.setSpan(customEmoji, matcher.start(), matcher.end(), 0);
                    Glide.with(view)
                            .asDrawable()
                            .load(animate ? emoji.url : emoji.static_url)
                            .into(customEmoji.getTarget(animate));
                }
            }
        }
        content = customEmoji.makeEmoji(content, emojiList, animate, callback);

        if (imagesToReplace.size() > 0) {
            for (Map.Entry<String, String> entry : imagesToReplace.entrySet()) {
@@ -183,12 +177,11 @@ public class SpannableHelper {
                Matcher matcher = Pattern.compile(key, Pattern.LITERAL)
                        .matcher(content);
                while (matcher.find()) {
                    CustomEmoji customEmoji = new CustomEmoji(new WeakReference<>(view));
                    content.setSpan(customEmoji, matcher.start(), matcher.end(), 0);
                    Glide.with(view)
                            .asDrawable()
                            .load(url)
                            .into(customEmoji.getTarget(animate));
                            .into(customEmoji.getTarget(animate, null));
                }
            }

@@ -1066,7 +1059,7 @@ public class SpannableHelper {
                        Glide.with(viewWeakReference.get())
                                .asDrawable()
                                .load(animate ? emoji.url : emoji.static_url)
                                .into(customEmoji.getTarget(animate));
                                .into(customEmoji.getTarget(animate, null));
                    }
                }
            }
+2 −2
Original line number Diff line number Diff line
@@ -1107,7 +1107,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
            StatusSimpleViewHolder holder = (StatusSimpleViewHolder) viewHolder;
            holder.binding.statusContent.setText(
                    status.getSpanContent(context,
                            new WeakReference<>(holder.binding.statusContent)),
                            new WeakReference<>(holder.binding.statusContent), null),
                    TextView.BufferType.SPANNABLE);
            MastodonHelper.loadPPMastodon(holder.binding.avatar, status.account);
            if (status.account != null) {
@@ -1122,7 +1122,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
                holder.binding.spoiler.setVisibility(View.VISIBLE);
                holder.binding.spoiler.setText(
                        status.getSpanSpoiler(context,
                                new WeakReference<>(holder.binding.spoiler)),
                                new WeakReference<>(holder.binding.spoiler), null),
                        TextView.BufferType.SPANNABLE);
            } else {
                holder.binding.spoiler.setVisibility(View.GONE);
+2 −2
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
            holder.binding.spoiler.setVisibility(View.VISIBLE);
            holder.binding.spoiler.setText(
                    conversation.last_status.getSpanSpoiler(context,
                            new WeakReference<>(holder.binding.spoiler)),
                            new WeakReference<>(holder.binding.spoiler), () -> notifyItemChanged(holder.getBindingAdapterPosition())),
                    TextView.BufferType.SPANNABLE);
        } else {
            holder.binding.spoiler.setVisibility(View.GONE);
@@ -161,7 +161,7 @@ public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
        //--- MAIN CONTENT ---
        holder.binding.statusContent.setText(
                conversation.last_status.getSpanContent(context,
                        new WeakReference<>(holder.binding.statusContent)),
                        new WeakReference<>(holder.binding.statusContent), () -> notifyItemChanged(holder.getBindingAdapterPosition())),
                TextView.BufferType.SPANNABLE);
        //--- DATE ---
        holder.binding.lastMessageDate.setText(Helper.dateDiff(context, conversation.last_status.created_at));
Loading