Fix custom emojis

This commit is contained in:
Thomas 2025-05-28 17:40:23 +02:00
parent 02a066a253
commit 2ff3e10303
14 changed files with 64 additions and 85 deletions

View file

@ -141,7 +141,7 @@ dependencies {
implementation("com.vanniktech:android-image-cropper:4.3.3") implementation("com.vanniktech:android-image-cropper:4.3.3")
annotationProcessor "com.github.bumptech.glide:compiler:4.12.0" annotationProcessor "com.github.bumptech.glide:compiler:4.12.0"
implementation 'jp.wasabeef:glide-transformations:4.3.0' implementation 'jp.wasabeef:glide-transformations:4.3.0'
implementation 'com.github.penfeizhou.android.animation:glide-plugin:2.23.0' implementation 'com.github.penfeizhou.android.animation:glide-plugin:3.0.5'
implementation 'androidx.media3:media3-exoplayer-hls:1.2.1' implementation 'androidx.media3:media3-exoplayer-hls:1.2.1'
implementation "androidx.media3:media3-exoplayer:1.2.1" implementation "androidx.media3:media3-exoplayer:1.2.1"
implementation "androidx.media3:media3-exoplayer-dash:1.2.1" implementation "androidx.media3:media3-exoplayer-dash:1.2.1"

View file

@ -540,13 +540,7 @@ public class ProfileActivity extends BaseActivity {
}); });
binding.accountNote.setText( binding.accountNote.setText(
account.getSpanNote(ProfileActivity.this, account.getSpanNote(ProfileActivity.this,
new WeakReference<>(binding.accountNote), () -> { new WeakReference<>(binding.accountNote)),
//TODO: replace this hack
binding.accountNote.setText(
account.getSpanNote(ProfileActivity.this,
new WeakReference<>(binding.accountNote)), TextView.BufferType.SPANNABLE);
}),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
binding.accountNote.setMovementMethod(LinkMovementMethod.getInstance()); binding.accountNote.setMovementMethod(LinkMovementMethod.getInstance());

View file

@ -95,7 +95,7 @@ public class Account implements Serializable {
if (display_name == null || display_name.isEmpty()) { if (display_name == null || display_name.isEmpty()) {
display_name = username; display_name = username;
} }
return SpannableHelper.convert(context, display_name, null, this, null, viewWeakReference, null, true, false); return SpannableHelper.convert(context, display_name, null, this, null, viewWeakReference, true, false);
} }
public synchronized Spannable getSpanDisplayNameEmoji(Activity activity, WeakReference<View> viewWeakReference) { public synchronized Spannable getSpanDisplayNameEmoji(Activity activity, WeakReference<View> viewWeakReference) {
@ -106,16 +106,14 @@ public class Account implements Serializable {
} }
public synchronized Spannable getSpanDisplayNameTitle(Context context, WeakReference<View> viewWeakReference, String title) { public synchronized Spannable getSpanDisplayNameTitle(Context context, WeakReference<View> viewWeakReference, String title) {
return SpannableHelper.convert(context, title, null, this, null, viewWeakReference, null, true, false); return SpannableHelper.convert(context, title, null, this, null, viewWeakReference, true, false);
} }
public synchronized Spannable getSpanNote(Context context, WeakReference<View> viewWeakReference) { public synchronized Spannable getSpanNote(Context context, WeakReference<View> viewWeakReference) {
return SpannableHelper.convert(context, note, null, this, null, viewWeakReference, null, true, false); return SpannableHelper.convert(context, note, null, this, null, viewWeakReference, true, false);
}
public synchronized Spannable getSpanNote(Context context, WeakReference<View> viewWeakReference, Status.Callback callback) {
return SpannableHelper.convert(context, note, null, this, null, viewWeakReference, callback, true, false);
} }
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable Object obj) {
boolean same = false; boolean same = false;

View file

@ -56,7 +56,7 @@ public class Announcement {
public synchronized Spannable getSpanContent(Context context, WeakReference<View> viewWeakReference) { public synchronized Spannable getSpanContent(Context context, WeakReference<View> viewWeakReference) {
return SpannableHelper.convert(context, content, null, null, this, viewWeakReference, null, true, false); return SpannableHelper.convert(context, content, null, null, this, viewWeakReference, true, false);
} }
} }

View file

@ -47,7 +47,7 @@ public class Field implements Serializable {
if (verified_at != null && value != null) { if (verified_at != null && value != null) {
value_span = new ForegroundColorSpan(ContextCompat.getColor(context, R.color.verified_text)); value_span = new ForegroundColorSpan(ContextCompat.getColor(context, R.color.verified_text));
} }
Spannable spannable = SpannableHelper.convert(context, value, null, account, null, viewWeakReference, null, true, false); Spannable spannable = SpannableHelper.convert(context, value, null, account, null, viewWeakReference, true, false);
if (value_span != null && spannable != null) { if (value_span != null && spannable != null) {
spannable.setSpan(value_span, 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); spannable.setSpan(value_span, 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} }
@ -57,7 +57,7 @@ public class Field implements Serializable {
public synchronized Spannable getLabelSpan(Context context, Account account, WeakReference<View> viewWeakReference) { public synchronized Spannable getLabelSpan(Context context, Account account, WeakReference<View> viewWeakReference) {
Spannable spannable = SpannableHelper.convert(context, name, null, account, null, viewWeakReference, null, true, false); Spannable spannable = SpannableHelper.convert(context, name, null, account, null, viewWeakReference, true, false);
if (name_span != null && spannable != null) { if (name_span != null && spannable != null) {
spannable.setSpan(name_span, 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); spannable.setSpan(name_span, 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} }

View file

@ -61,7 +61,7 @@ public class Poll implements Serializable {
public transient Spannable span_title; public transient Spannable span_title;
public Spannable getSpanTitle(Context context, Status status, WeakReference<View> viewWeakReference) { public Spannable getSpanTitle(Context context, Status status, WeakReference<View> viewWeakReference) {
span_title = SpannableHelper.convert(context, title, status, null, null, viewWeakReference, null, false, false); span_title = SpannableHelper.convert(context, title, status, null, null, viewWeakReference, false, false);
return span_title; return span_title;
} }
} }

View file

@ -155,23 +155,23 @@ public class Status implements Serializable, Cloneable {
return same; return same;
} }
public synchronized Spannable getSpanContent(Context context, boolean checkRemotely, WeakReference<View> viewWeakReference, Callback callback) { public synchronized Spannable getSpanContent(Context context, boolean checkRemotely, WeakReference<View> viewWeakReference) {
if (contentSpan == null) { if (contentSpan == null) {
contentSpan = SpannableHelper.convert(context, content, this, null, null, checkRemotely, viewWeakReference, callback, true, true); contentSpan = SpannableHelper.convert(context, content, this, null, null, checkRemotely, viewWeakReference, true, true);
} }
return contentSpan; return contentSpan;
} }
public synchronized Spannable getSpanSpoiler(Context context, WeakReference<View> viewWeakReference, Callback callback) { public synchronized Spannable getSpanSpoiler(Context context, WeakReference<View> viewWeakReference) {
if (contentSpoilerSpan == null) { if (contentSpoilerSpan == null) {
contentSpoilerSpan = SpannableHelper.convert(context, spoiler_text, this, null, null, viewWeakReference, callback, true, false); contentSpoilerSpan = SpannableHelper.convert(context, spoiler_text, this, null, null, viewWeakReference, true, false);
} }
return contentSpoilerSpan; return contentSpoilerSpan;
} }
public synchronized Spannable getSpanTranslate(Context context, WeakReference<View> viewWeakReference, Callback callback) { public synchronized Spannable getSpanTranslate(Context context, WeakReference<View> viewWeakReference) {
if (contentTranslateSpan == null) { if (contentTranslateSpan == null) {
contentTranslateSpan = SpannableHelper.convert(context, translationContent, this, null, null, viewWeakReference, callback, true, true); contentTranslateSpan = SpannableHelper.convert(context, translationContent, this, null, null, viewWeakReference, true, true);
} }
return contentTranslateSpan; return contentTranslateSpan;
} }

View file

@ -20,22 +20,20 @@ import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition; import com.bumptech.glide.request.transition.Transition;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import app.fedilab.android.R; import app.fedilab.android.R;
import app.fedilab.android.mastodon.client.entities.api.Emoji; import app.fedilab.android.mastodon.client.entities.api.Emoji;
import app.fedilab.android.mastodon.client.entities.api.Status;
public class CustomEmoji extends ReplacementSpan {
public class CustomImageSpan extends ReplacementSpan {
private final WeakReference<View> viewWeakReference; private final WeakReference<View> viewWeakReference;
private float scale; private float scale;
private Drawable imageDrawable; private Drawable imageDrawable;
private boolean callbackCalled;
CustomEmoji(WeakReference<View> viewWeakReference) { CustomImageSpan(WeakReference<View> viewWeakReference) {
Context mContext = viewWeakReference.get().getContext(); Context mContext = viewWeakReference.get().getContext();
this.viewWeakReference = viewWeakReference; this.viewWeakReference = viewWeakReference;
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(mContext); SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
@ -43,27 +41,21 @@ public class CustomEmoji extends ReplacementSpan {
if (scale > 1.3f) { if (scale > 1.3f) {
scale = 1.3f; scale = 1.3f;
} }
callbackCalled = false;
} }
public SpannableStringBuilder makeEmoji(SpannableStringBuilder content, List<Emoji> emojiList, boolean animate, Status.Callback callback) { public void makeEmoji(SpannableStringBuilder content, Emoji emoji, boolean animate) {
if (emojiList != null && emojiList.size() > 0) { if (emoji != null) {
int count = 1; Matcher matcher = Pattern.compile(":" + emoji.shortcode + ":", Pattern.LITERAL)
for (Emoji emoji : emojiList) { .matcher(content);
Matcher matcher = Pattern.compile(":" + emoji.shortcode + ":", Pattern.LITERAL) while (matcher.find()) {
.matcher(content); CustomImageSpan customEmoji = new CustomImageSpan(new WeakReference<>(viewWeakReference.get()));
while (matcher.find()) { content.setSpan(customEmoji, matcher.start(), matcher.end(), 0);
CustomEmoji customEmoji = new CustomEmoji(new WeakReference<>(viewWeakReference.get())); Glide.with(viewWeakReference.get())
content.setSpan(customEmoji, matcher.start(), matcher.end(), 0); .asDrawable()
Glide.with(viewWeakReference.get()) .load(animate ? emoji.url : emoji.static_url)
.asDrawable() .into(customEmoji.getTarget(animate));
.load(animate ? emoji.url : emoji.static_url)
.into(customEmoji.getTarget(animate, count == emojiList.size() && !callbackCalled ? callback : null));
}
count++;
} }
} }
return content;
} }
@Override @Override
@ -85,15 +77,15 @@ public class CustomEmoji extends ReplacementSpan {
int emojiSize = (int) (paint.getTextSize() * scale); int emojiSize = (int) (paint.getTextSize() * scale);
imageDrawable.setBounds(0, 0, emojiSize, emojiSize); imageDrawable.setBounds(0, 0, emojiSize, emojiSize);
int transY = bottom - imageDrawable.getBounds().bottom; int transY = bottom - imageDrawable.getBounds().bottom;
transY -= paint.getFontMetrics().descent / 2; transY -= (int) (paint.getFontMetrics().descent / 2);
canvas.translate(x, (float) transY); canvas.translate(x, (float) transY);
imageDrawable.draw(canvas); imageDrawable.draw(canvas);
canvas.restore(); canvas.restore();
} }
} }
public Target<Drawable> getTarget(boolean animate, Status.Callback callback) { public Target<Drawable> getTarget(boolean animate) {
return new CustomTarget<Drawable>() { return new CustomTarget<>() {
@Override @Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) { public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
View view = viewWeakReference.get(); View view = viewWeakReference.get();
@ -131,10 +123,6 @@ public class CustomEmoji extends ReplacementSpan {
if (view != null) { if (view != null) {
view.invalidate(); view.invalidate();
} }
if (callback != null && !callbackCalled) {
callbackCalled = true;
callback.emojiFetched();
}
} }
@Override @Override

View file

@ -109,13 +109,13 @@ public class SpannableHelper {
public static Spannable convert(Context context, String text, public static Spannable convert(Context context, String text,
Status status, Account account, Announcement announcement, Status status, Account account, Announcement announcement,
WeakReference<View> viewWeakReference, Status.Callback callback, boolean convertHtml, boolean convertMarkdown) { WeakReference<View> viewWeakReference, boolean convertHtml, boolean convertMarkdown) {
return convert(context, text, status, account, announcement, false, viewWeakReference, callback, convertHtml, convertMarkdown); return convert(context, text, status, account, announcement, false, viewWeakReference, convertHtml, convertMarkdown);
} }
public static Spannable convert(Context context, String text, public static Spannable convert(Context context, String text,
Status status, Account account, Announcement announcement, boolean checkRemotely, Status status, Account account, Announcement announcement, boolean checkRemotely,
WeakReference<View> viewWeakReference, Status.Callback callback, boolean convertHtml, boolean convertMarkdown) { WeakReference<View> viewWeakReference, boolean convertHtml, boolean convertMarkdown) {
if (text == null) { if (text == null) {
return null; return null;
} }
@ -365,7 +365,6 @@ public class SpannableHelper {
text = text.replaceAll(Pattern.quote(matcherImg.group()), replacement); text = text.replaceAll(Pattern.quote(matcherImg.group()), replacement);
} }
View view = viewWeakReference.get();
List<Emoji> emojiList = null; List<Emoji> emojiList = null;
if (status != null) { if (status != null) {
emojiList = status.emojis; emojiList = status.emojis;
@ -375,21 +374,26 @@ public class SpannableHelper {
emojiList = announcement.emojis; emojiList = announcement.emojis;
} }
boolean animate = !sharedpreferences.getBoolean(context.getString(R.string.SET_DISABLE_ANIMATED_EMOJI), false); boolean animate = !sharedpreferences.getBoolean(context.getString(R.string.SET_DISABLE_ANIMATED_EMOJI), false);
CustomEmoji customEmoji = new CustomEmoji(new WeakReference<>(view)); if(emojiList != null) {
content = customEmoji.makeEmoji(content, emojiList, animate, callback); emojiList.forEach(emoji -> {
CustomImageSpan customImageSpan = new CustomImageSpan(viewWeakReference);
customImageSpan.makeEmoji(content, emoji, animate);
});
}
if (!imagesToReplace.isEmpty()) { if (!imagesToReplace.isEmpty()) {
for (Map.Entry<String, String> entry : imagesToReplace.entrySet()) { for (Map.Entry<String, String> entry : imagesToReplace.entrySet()) {
CustomImageSpan customImageSpan = new CustomImageSpan(viewWeakReference);
String key = entry.getKey(); String key = entry.getKey();
String url = entry.getValue(); String url = entry.getValue();
Matcher matcher = Pattern.compile(key, Pattern.LITERAL) Matcher matcher = Pattern.compile(key, Pattern.LITERAL)
.matcher(content); .matcher(content);
while (matcher.find()) { while (matcher.find()) {
content.setSpan(customEmoji, matcher.start(), matcher.end(), 0); content.setSpan(customImageSpan, matcher.start(), matcher.end(), 0);
Glide.with(view) Glide.with(viewWeakReference.get().getContext())
.asDrawable() .asDrawable()
.load(url) .load(url)
.into(customEmoji.getTarget(animate, null)); .into(customImageSpan.getTarget(animate));
} }
} }
@ -990,18 +994,18 @@ public class SpannableHelper {
List<Emoji> emojiList = account.emojis; List<Emoji> emojiList = account.emojis;
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity); SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity);
boolean animate = !sharedpreferences.getBoolean(activity.getString(R.string.SET_DISABLE_ANIMATED_EMOJI), false); boolean animate = !sharedpreferences.getBoolean(activity.getString(R.string.SET_DISABLE_ANIMATED_EMOJI), false);
if (emojiList != null && emojiList.size() > 0) { if (emojiList != null && !emojiList.isEmpty()) {
for (Emoji emoji : emojiList) { for (Emoji emoji : emojiList) {
Matcher matcher = Pattern.compile(":" + emoji.shortcode + ":", Pattern.LITERAL) Matcher matcher = Pattern.compile(":" + emoji.shortcode + ":", Pattern.LITERAL)
.matcher(content); .matcher(content);
while (matcher.find()) { while (matcher.find()) {
CustomEmoji customEmoji = new CustomEmoji(new WeakReference<>(viewWeakReference.get())); CustomImageSpan customImageSpan = new CustomImageSpan(viewWeakReference);
content.setSpan(customEmoji, matcher.start(), matcher.end(), 0); content.setSpan(customImageSpan, matcher.start(), matcher.end(), 0);
if (Helper.isValidContextForGlide(activity)) { if (Helper.isValidContextForGlide(activity)) {
Glide.with(viewWeakReference.get()) Glide.with(viewWeakReference.get().getContext())
.asDrawable() .asDrawable()
.load(animate ? emoji.url : emoji.static_url) .load(animate ? emoji.url : emoji.static_url)
.into(customEmoji.getTarget(animate, null)); .into(customImageSpan.getTarget(animate));
} }
} }
} }

View file

@ -1418,7 +1418,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
} }
holder.binding.statusContent.setText( holder.binding.statusContent.setText(
status.getSpanContent(context, false, status.getSpanContent(context, false,
new WeakReference<>(holder.binding.statusContent), () -> mRecyclerView.post(() -> notifyItemChanged(position))), new WeakReference<>(holder.binding.statusContent)),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
holder.binding.statusContent.setMovementMethod(LongClickLinkMovementMethod.getInstance()); holder.binding.statusContent.setMovementMethod(LongClickLinkMovementMethod.getInstance());
MastodonHelper.loadPPMastodon(holder.binding.avatar, status.account); MastodonHelper.loadPPMastodon(holder.binding.avatar, status.account);
@ -1434,7 +1434,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
holder.binding.spoiler.setVisibility(View.VISIBLE); holder.binding.spoiler.setVisibility(View.VISIBLE);
holder.binding.spoiler.setText( holder.binding.spoiler.setText(
status.getSpanSpoiler(context, status.getSpanSpoiler(context,
new WeakReference<>(holder.binding.spoiler), null), new WeakReference<>(holder.binding.spoiler)),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
} else { } else {
holder.binding.spoiler.setVisibility(View.GONE); holder.binding.spoiler.setVisibility(View.GONE);

View file

@ -199,7 +199,7 @@ public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
holder.binding.spoiler.setVisibility(View.VISIBLE); holder.binding.spoiler.setVisibility(View.VISIBLE);
holder.binding.spoiler.setText( holder.binding.spoiler.setText(
conversation.last_status.getSpanSpoiler(context, conversation.last_status.getSpanSpoiler(context,
new WeakReference<>(holder.binding.spoiler), () -> mRecyclerView.post(() -> notifyItemChanged(holder.getBindingAdapterPosition()))), new WeakReference<>(holder.binding.spoiler)),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
} else { } else {
holder.binding.spoiler.setVisibility(View.GONE); holder.binding.spoiler.setVisibility(View.GONE);
@ -209,7 +209,7 @@ public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
//--- MAIN CONTENT --- //--- MAIN CONTENT ---
holder.binding.statusContent.setText( holder.binding.statusContent.setText(
conversation.last_status.getSpanContent(context, false, conversation.last_status.getSpanContent(context, false,
new WeakReference<>(holder.binding.statusContent), () -> mRecyclerView.post(() -> notifyItemChanged(holder.getBindingAdapterPosition()))), new WeakReference<>(holder.binding.statusContent)),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
//--- DATE --- //--- DATE ---
holder.binding.lastMessageDate.setText(Helper.dateDiff(context, conversation.last_status.created_at)); holder.binding.lastMessageDate.setText(Helper.dateDiff(context, conversation.last_status.created_at));

View file

@ -604,7 +604,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
holder.binding.quotedMessage.cardviewContainer.setStrokeColor(ThemeHelper.getAttColor(context, R.attr.colorPrimary)); holder.binding.quotedMessage.cardviewContainer.setStrokeColor(ThemeHelper.getAttColor(context, R.attr.colorPrimary));
holder.binding.quotedMessage.statusContent.setText( holder.binding.quotedMessage.statusContent.setText(
statusToDeal.quote.getSpanContent(context, remote, statusToDeal.quote.getSpanContent(context, remote,
new WeakReference<>(holder.binding.quotedMessage.statusContent), null), new WeakReference<>(holder.binding.quotedMessage.statusContent)),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
MastodonHelper.loadPPMastodon(holder.binding.quotedMessage.avatar, statusToDeal.quote.account); MastodonHelper.loadPPMastodon(holder.binding.quotedMessage.avatar, statusToDeal.quote.account);
if (statusToDeal.quote.account != null) { if (statusToDeal.quote.account != null) {
@ -619,7 +619,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
holder.binding.quotedMessage.spoiler.setVisibility(View.VISIBLE); holder.binding.quotedMessage.spoiler.setVisibility(View.VISIBLE);
holder.binding.quotedMessage.spoiler.setText( holder.binding.quotedMessage.spoiler.setText(
statusToDeal.quote.getSpanSpoiler(context, statusToDeal.quote.getSpanSpoiler(context,
new WeakReference<>(holder.binding.quotedMessage.spoiler), null), new WeakReference<>(holder.binding.quotedMessage.spoiler)),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
} else { } else {
holder.binding.quotedMessage.spoiler.setVisibility(View.GONE); holder.binding.quotedMessage.spoiler.setVisibility(View.GONE);
@ -1440,7 +1440,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
holder.binding.spoiler.setVisibility(View.VISIBLE); holder.binding.spoiler.setVisibility(View.VISIBLE);
holder.binding.spoiler.setText( holder.binding.spoiler.setText(
statusToDeal.getSpanSpoiler(context, statusToDeal.getSpanSpoiler(context,
new WeakReference<>(holder.binding.spoiler), () -> recyclerView.post(() -> adapter.notifyItemChanged(holder.getBindingAdapterPosition()))), new WeakReference<>(holder.binding.spoiler)),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
statusToDeal.isExpended = true; statusToDeal.isExpended = true;
} else { } else {
@ -1453,7 +1453,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
holder.binding.spoiler.setText( holder.binding.spoiler.setText(
statusToDeal.getSpanSpoiler(context, statusToDeal.getSpanSpoiler(context,
new WeakReference<>(holder.binding.spoiler), () -> recyclerView.post(() -> adapter.notifyItemChanged(holder.getBindingAdapterPosition()))), new WeakReference<>(holder.binding.spoiler)),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
} }
if (statusToDeal.isExpended) { if (statusToDeal.isExpended) {
@ -1506,9 +1506,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
//--- MAIN CONTENT --- //--- MAIN CONTENT ---
holder.binding.statusContent.setText( holder.binding.statusContent.setText(
statusToDeal.getSpanContent(context, remote, statusToDeal.getSpanContent(context, remote,
new WeakReference<>(holder.binding.statusContent), () -> { new WeakReference<>(holder.binding.statusContent)),
recyclerView.post(() -> adapter.notifyItemChanged(holder.getBindingAdapterPosition()));
}),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
if (truncate_toots_size > 0) { if (truncate_toots_size > 0) {
holder.binding.statusContent.setMaxLines(truncate_toots_size); holder.binding.statusContent.setMaxLines(truncate_toots_size);
@ -1533,9 +1531,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
holder.binding.containerTrans.setVisibility(View.VISIBLE); holder.binding.containerTrans.setVisibility(View.VISIBLE);
holder.binding.statusContentTranslated.setText( holder.binding.statusContentTranslated.setText(
statusToDeal.getSpanTranslate(context, statusToDeal.getSpanTranslate(context,
new WeakReference<>(holder.binding.statusContentTranslated), () -> { new WeakReference<>(holder.binding.statusContentTranslated)),
recyclerView.post(() -> adapter.notifyItemChanged(holder.getBindingAdapterPosition()));
}),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
} else { } else {
holder.binding.containerTrans.setVisibility(View.GONE); holder.binding.containerTrans.setVisibility(View.GONE);

View file

@ -241,8 +241,7 @@ public class StatusDirectMessageAdapter extends RecyclerView.Adapter<RecyclerVie
status.underlined = true; status.underlined = true;
holder.binding.messageContent.setText( holder.binding.messageContent.setText(
status.getSpanContent(context, false, status.getSpanContent(context, false,
new WeakReference<>(holder.binding.messageContent), new WeakReference<>(holder.binding.messageContent)),
() -> mRecyclerView.post(() -> notifyItemChanged(holder.getBindingAdapterPosition()))),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
holder.binding.messageContent.setMovementMethod(LongClickLinkMovementMethod.getInstance()); holder.binding.messageContent.setMovementMethod(LongClickLinkMovementMethod.getInstance());
if (measuredWidth <= 0 && status.media_attachments != null && status.media_attachments.size() > 0) { if (measuredWidth <= 0 && status.media_attachments != null && status.media_attachments.size() > 0) {

View file

@ -56,13 +56,13 @@ public class StatusHistoryAdapter extends RecyclerView.Adapter<RecyclerView.View
Status status = statuses.get(position); Status status = statuses.get(position);
holder.binding.statusContent.setText( holder.binding.statusContent.setText(
status.getSpanContent(context, false, status.getSpanContent(context, false,
new WeakReference<>(holder.binding.statusContent), null), new WeakReference<>(holder.binding.statusContent)),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
if (status.spoiler_text != null && !status.spoiler_text.trim().isEmpty()) { if (status.spoiler_text != null && !status.spoiler_text.trim().isEmpty()) {
holder.binding.spoiler.setVisibility(View.VISIBLE); holder.binding.spoiler.setVisibility(View.VISIBLE);
holder.binding.spoiler.setText( holder.binding.spoiler.setText(
status.getSpanSpoiler(context, status.getSpanSpoiler(context,
new WeakReference<>(holder.binding.spoiler), null), new WeakReference<>(holder.binding.spoiler)),
TextView.BufferType.SPANNABLE); TextView.BufferType.SPANNABLE);
} else { } else {
holder.binding.spoiler.setVisibility(View.GONE); holder.binding.spoiler.setVisibility(View.GONE);