Some tries

This commit is contained in:
Thomas 2022-07-13 12:50:48 +02:00
parent 455e5666a9
commit c17322c699
13 changed files with 257 additions and 108 deletions

View File

@ -268,86 +268,74 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana
} }
}); });
} else if (statusDraft != null) {//Restore a draft with all messages } else if (statusDraft != null) {//Restore a draft with all messages
new Thread(() -> { if (statusDraft.statusReplyList != null) {
if (statusDraft.statusReplyList != null) { statusDraft.statusReplyList = SpannableHelper.convertStatus(getApplication().getApplicationContext(), statusDraft.statusReplyList);
statusDraft.statusReplyList = SpannableHelper.convertStatus(getApplication().getApplicationContext(), statusDraft.statusReplyList); }
} if (statusDraft.statusReplyList != null) {
Handler mainHandler = new Handler(Looper.getMainLooper()); statusList.addAll(statusDraft.statusReplyList);
Runnable myRunnable = () -> { binding.recyclerView.addItemDecoration(new DividerDecorationSimple(ComposeActivity.this, statusList));
if (statusDraft.statusReplyList != null) { }
statusList.addAll(statusDraft.statusReplyList); int statusCount = statusList.size();
binding.recyclerView.addItemDecoration(new DividerDecorationSimple(ComposeActivity.this, statusList)); statusList.addAll(statusDraft.statusDraftList);
} composeAdapter = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility);
int statusCount = statusList.size(); composeAdapter.manageDrafts = this;
statusList.addAll(statusDraft.statusDraftList); LinearLayoutManager mLayoutManager = new LinearLayoutManager(ComposeActivity.this);
composeAdapter = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility); binding.recyclerView.setLayoutManager(mLayoutManager);
composeAdapter.manageDrafts = this; binding.recyclerView.setAdapter(composeAdapter);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(ComposeActivity.this); binding.recyclerView.scrollToPosition(composeAdapter.getItemCount() - 1);
binding.recyclerView.setLayoutManager(mLayoutManager);
binding.recyclerView.setAdapter(composeAdapter);
binding.recyclerView.scrollToPosition(composeAdapter.getItemCount() - 1);
};
mainHandler.post(myRunnable);
}).start();
} else if (statusReply != null) { } else if (statusReply != null) {
new Thread(() -> { statusReply = SpannableHelper.convertStatus(getApplication().getApplicationContext(), statusReply);
statusReply = SpannableHelper.convertStatus(getApplication().getApplicationContext(), statusReply); statusList.add(statusReply);
Handler mainHandler = new Handler(Looper.getMainLooper()); int statusCount = statusList.size();
Runnable myRunnable = () -> { statusDraftList.get(0).in_reply_to_id = statusReply.id;
statusList.add(statusReply); //We change order for mentions
int statusCount = statusList.size(); //At first place the account that has been mentioned if it's not our
statusDraftList.get(0).in_reply_to_id = statusReply.id; statusDraftList.get(0).mentions = new ArrayList<>();
//We change order for mentions if (!statusReply.account.acct.equalsIgnoreCase(currentAccount.mastodon_account.acct)) {
//At first place the account that has been mentioned if it's not our Mention mention = new Mention();
statusDraftList.get(0).mentions = new ArrayList<>(); mention.acct = "@" + statusReply.account.acct;
if (!statusReply.account.acct.equalsIgnoreCase(currentAccount.mastodon_account.acct)) { mention.url = statusReply.account.url;
Mention mention = new Mention(); mention.username = statusReply.account.username;
mention.acct = "@" + statusReply.account.acct; statusDraftList.get(0).mentions.add(mention);
mention.url = statusReply.account.url; }
mention.username = statusReply.account.username;
statusDraftList.get(0).mentions.add(mention);
}
//There are other mentions to //There are other mentions to
if (statusReply.mentions != null && statusReply.mentions.size() > 0) { if (statusReply.mentions != null && statusReply.mentions.size() > 0) {
for (Mention mentionTmp : statusReply.mentions) { for (Mention mentionTmp : statusReply.mentions) {
if (!mentionTmp.acct.equalsIgnoreCase(statusReply.account.acct) && !mentionTmp.acct.equalsIgnoreCase(currentAccount.mastodon_account.acct)) { if (!mentionTmp.acct.equalsIgnoreCase(statusReply.account.acct) && !mentionTmp.acct.equalsIgnoreCase(currentAccount.mastodon_account.acct)) {
statusDraftList.get(0).mentions.add(mentionTmp); statusDraftList.get(0).mentions.add(mentionTmp);
}
}
} }
if (mentionBooster != null) { }
Mention mention = new Mention(); }
mention.acct = mentionBooster.acct; if (mentionBooster != null) {
mention.url = mentionBooster.url; Mention mention = new Mention();
mention.username = mentionBooster.username; mention.acct = mentionBooster.acct;
boolean present = false; mention.url = mentionBooster.url;
for (Mention mentionTmp : statusDraftList.get(0).mentions) { mention.username = mentionBooster.username;
if (mentionTmp.acct.equalsIgnoreCase(mentionBooster.acct)) { boolean present = false;
present = true; for (Mention mentionTmp : statusDraftList.get(0).mentions) {
break; if (mentionTmp.acct.equalsIgnoreCase(mentionBooster.acct)) {
} present = true;
} break;
if (!present) {
statusDraftList.get(0).mentions.add(mention);
}
} }
if (statusReply.spoiler_text != null) { }
statusDraftList.get(0).spoiler_text = statusReply.spoiler_text; if (!present) {
} statusDraftList.get(0).mentions.add(mention);
//StatusDraftList at this point should only have one element }
statusList.addAll(statusDraftList); }
composeAdapter = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility); if (statusReply.spoiler_text != null) {
composeAdapter.manageDrafts = this; statusDraftList.get(0).spoiler_text = statusReply.spoiler_text;
LinearLayoutManager mLayoutManager = new LinearLayoutManager(ComposeActivity.this); }
binding.recyclerView.setLayoutManager(mLayoutManager); //StatusDraftList at this point should only have one element
binding.recyclerView.setAdapter(composeAdapter); statusList.addAll(statusDraftList);
statusesVM.getContext(currentInstance, BaseMainActivity.currentToken, statusReply.id) composeAdapter = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility);
.observe(ComposeActivity.this, this::initializeContextView); composeAdapter.manageDrafts = this;
}; LinearLayoutManager mLayoutManager = new LinearLayoutManager(ComposeActivity.this);
mainHandler.post(myRunnable); binding.recyclerView.setLayoutManager(mLayoutManager);
}).start(); binding.recyclerView.setAdapter(composeAdapter);
statusesVM.getContext(currentInstance, BaseMainActivity.currentToken, statusReply.id)
.observe(ComposeActivity.this, this::initializeContextView);
} else { } else {
//Compose without replying //Compose without replying
statusList.addAll(statusDraftList); statusList.addAll(statusDraftList);
@ -359,7 +347,6 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana
if (statusMention != null) { if (statusMention != null) {
composeAdapter.loadMentions(statusMention); composeAdapter.loadMentions(statusMention);
} }
} }
MastodonHelper.loadPPMastodon(binding.profilePicture, account.mastodon_account); MastodonHelper.loadPPMastodon(binding.profilePicture, account.mastodon_account);
LocalBroadcastManager.getInstance(this) LocalBroadcastManager.getInstance(this)

View File

@ -32,6 +32,7 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.text.Html; import android.text.Html;
import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.Spanned; import android.text.Spanned;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
@ -89,6 +90,7 @@ import app.fedilab.android.client.entities.app.WellKnownNodeinfo;
import app.fedilab.android.databinding.ActivityProfileBinding; import app.fedilab.android.databinding.ActivityProfileBinding;
import app.fedilab.android.exception.DBException; import app.fedilab.android.exception.DBException;
import app.fedilab.android.helper.CrossActionHelper; import app.fedilab.android.helper.CrossActionHelper;
import app.fedilab.android.helper.CustomEmoji;
import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.Helper;
import app.fedilab.android.helper.MastodonHelper; import app.fedilab.android.helper.MastodonHelper;
import app.fedilab.android.helper.SpannableHelper; import app.fedilab.android.helper.SpannableHelper;
@ -362,7 +364,9 @@ public class ProfileActivity extends BaseActivity {
if (account.span_display_name == null && account.display_name == null) { if (account.span_display_name == null && account.display_name == null) {
binding.accountDn.setText(account.username); binding.accountDn.setText(account.username);
} else { } else {
binding.accountDn.setText(account.span_display_name != null ? account.span_display_name : account.display_name, TextView.BufferType.SPANNABLE); Spannable textAccount = account.span_display_name != null ? account.span_display_name : new SpannableString(account.display_name);
CustomEmoji.displayEmoji(ProfileActivity.this, account.emojis, textAccount, binding.accountDn, null, null);
binding.accountDn.setText(textAccount, TextView.BufferType.SPANNABLE);
} }
binding.accountUn.setText(String.format("@%s", account.acct)); binding.accountUn.setText(String.format("@%s", account.acct));
@ -377,12 +381,13 @@ public class ProfileActivity extends BaseActivity {
clipboard.setPrimaryClip(clip); clipboard.setPrimaryClip(clip);
return false; return false;
}); });
Spannable textNote;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
binding.accountNote.setText(account.span_note != null ? account.span_note : new SpannableString(Html.fromHtml(account.note, Html.FROM_HTML_MODE_COMPACT)), TextView.BufferType.SPANNABLE); textNote = account.span_note != null ? account.span_note : new SpannableString(Html.fromHtml(account.note, Html.FROM_HTML_MODE_COMPACT));
else else
binding.accountNote.setText(account.span_note != null ? account.span_note : new SpannableString(Html.fromHtml(account.note)), TextView.BufferType.SPANNABLE); textNote = account.span_note != null ? account.span_note : new SpannableString(Html.fromHtml(account.note));
CustomEmoji.displayEmoji(ProfileActivity.this, account.emojis, textNote, binding.accountNote, null, null);
binding.accountNote.setText(textNote, TextView.BufferType.SPANNABLE);
binding.accountNote.setMovementMethod(LinkMovementMethod.getInstance()); binding.accountNote.setMovementMethod(LinkMovementMethod.getInstance());
MastodonHelper.loadPPMastodon(binding.accountPp, account); MastodonHelper.loadPPMastodon(binding.accountPp, account);

View File

@ -78,7 +78,7 @@ public class Account implements Serializable {
public transient Spannable span_display_name; public transient Spannable span_display_name;
public transient Spannable span_note; public transient Spannable span_note;
public transient RelationShip relationShip; public transient RelationShip relationShip;
public boolean emojiFetched = false; public transient boolean emojiFetched = false;
public static class AccountParams implements Serializable { public static class AccountParams implements Serializable {
@SerializedName("discoverable") @SerializedName("discoverable")

View File

@ -51,4 +51,5 @@ public class Announcement {
//Some extra spannable element - They will be filled automatically when fetching the status //Some extra spannable element - They will be filled automatically when fetching the status
public transient Spannable span_content; public transient Spannable span_content;
public boolean emojiFetched = false;
} }

View File

@ -16,6 +16,7 @@ package app.fedilab.android.helper;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.text.Spannable; import android.text.Spannable;
import android.text.style.ImageSpan; import android.text.style.ImageSpan;
@ -28,7 +29,6 @@ import androidx.preference.PreferenceManager;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition; import com.bumptech.glide.request.transition.Transition;
import com.github.penfeizhou.animation.apng.APNGDrawable;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -54,13 +54,16 @@ public class CustomEmoji {
@Override @Override
public void onLoadFailed(@Nullable Drawable errorDrawable) { public void onLoadFailed(@Nullable Drawable errorDrawable) {
super.onLoadFailed(errorDrawable); super.onLoadFailed(errorDrawable);
if (finalCount == emojis.size()) { if (finalCount == emojis.size() && listener != null) {
listener.allEmojisfound(id); listener.allEmojisfound(id);
} }
} }
@Override @Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) { public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
if (content == null) {
return;
}
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()) {
@ -72,7 +75,7 @@ public class CustomEmoji {
imageSpan, matcher.start(), imageSpan, matcher.start(),
matcher.end(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); matcher.end(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
} }
if (animate && resource instanceof APNGDrawable) { if (animate && resource instanceof Animatable) {
Drawable.Callback callback = resource.getCallback(); Drawable.Callback callback = resource.getCallback();
resource.setCallback(new Drawable.Callback() { resource.setCallback(new Drawable.Callback() {
@Override @Override
@ -97,10 +100,10 @@ public class CustomEmoji {
} }
} }
}); });
((APNGDrawable) resource).start(); ((Animatable) resource).start();
} }
if (finalCount == emojis.size()) { if (finalCount == emojis.size() && listener != null) {
listener.allEmojisfound(id); listener.allEmojisfound(id);
} }
} }

View File

@ -861,31 +861,29 @@ public class SpannableHelper {
return statuses; return statuses;
} }
public static List<Status> convertNitterStatus(Context context, List<Status> statuses) { public static List<Status> convertNitterStatus(List<Status> statuses) {
if (statuses != null) { if (statuses != null) {
for (Status status : statuses) { for (Status status : statuses) {
convertNitterStatus(context, status); convertNitterStatus(status);
} }
} }
return statuses; return statuses;
} }
public static Status convertNitterStatus(Context context, Status status) { public static void convertNitterStatus(Status status) {
if (status != null) { if (status != null) {
status.span_content = SpannableHelper.convertNitter(context, status.content); status.span_content = SpannableHelper.convertNitter(status.content);
} }
return status;
} }
/** /**
* Convert HTML content to text. Also, it handles click on link * Convert HTML content to text. Also, it handles click on link
* This needs to be run asynchronously * This needs to be run asynchronously
* *
* @param context {@link Context} * @param text String - text to convert, it can be content, spoiler, poll items, etc.
* @param text String - text to convert, it can be content, spoiler, poll items, etc.
* @return Spannable string * @return Spannable string
*/ */
private static Spannable convertNitter(@NonNull Context context, String text) { private static Spannable convertNitter(String text) {
SpannableString initialContent; SpannableString initialContent;
if (text == null) { if (text == null) {
return null; return null;
@ -924,7 +922,7 @@ public class SpannableHelper {
if (status.account == null) { if (status.account == null) {
return status; return status;
} }
status.account.span_display_name = SpannableHelper.convertA(context, status.account, status.account.display_name, true); status.account.span_display_name = SpannableHelper.convertA(context, status.account.display_name, true);
if (status.poll != null) { if (status.poll != null) {
for (Poll.PollItem pollItem : status.poll.options) { for (Poll.PollItem pollItem : status.poll.options) {
pollItem.span_title = SpannableHelper.convert(context, status, pollItem.title, false); pollItem.span_title = SpannableHelper.convert(context, status, pollItem.title, false);
@ -936,7 +934,7 @@ public class SpannableHelper {
status.reblog.span_translate = SpannableHelper.convert(context, status, status.reblog.translationContent); status.reblog.span_translate = SpannableHelper.convert(context, status, status.reblog.translationContent);
} }
status.reblog.span_spoiler_text = SpannableHelper.convert(context, status, status.reblog.spoiler_text); status.reblog.span_spoiler_text = SpannableHelper.convert(context, status, status.reblog.spoiler_text);
status.reblog.account.span_display_name = SpannableHelper.convertA(context, status.reblog.account, status.reblog.account.display_name, true); status.reblog.account.span_display_name = SpannableHelper.convertA(context, status.reblog.account.display_name, true);
if (status.reblog.poll != null) { if (status.reblog.poll != null) {
for (Poll.PollItem pollItem : status.reblog.poll.options) { for (Poll.PollItem pollItem : status.reblog.poll.options) {
pollItem.span_title = SpannableHelper.convert(context, status, pollItem.title, false); pollItem.span_title = SpannableHelper.convert(context, status, pollItem.title, false);
@ -959,12 +957,12 @@ public class SpannableHelper {
public static Account convertAccount(Context context, Account account) { public static Account convertAccount(Context context, Account account) {
if (account != null) { if (account != null) {
account.span_display_name = SpannableHelper.convertA(context, account, account.display_name, true); account.span_display_name = SpannableHelper.convertA(context, account.display_name, true);
account.span_note = SpannableHelper.convertA(context, account, account.note, false); account.span_note = SpannableHelper.convertA(context, account.note, false);
if (account.fields != null && account.fields.size() > 0) { if (account.fields != null && account.fields.size() > 0) {
List<Field> fields = new ArrayList<>(); List<Field> fields = new ArrayList<>();
for (Field field : account.fields) { for (Field field : account.fields) {
field.value_span = SpannableHelper.convertA(context, account, field.value, false); field.value_span = SpannableHelper.convertA(context, field.value, false);
fields.add(field); fields.add(field);
} }
account.fields = fields; account.fields = fields;
@ -979,11 +977,10 @@ public class SpannableHelper {
* This needs to be run asynchronously * This needs to be run asynchronously
* *
* @param context {@link Context} * @param context {@link Context}
* @param account {@link Account} - Account concerned by the spannable transformation
* @param text String - text to convert, it can be display name or bio * @param text String - text to convert, it can be display name or bio
* @return Spannable string * @return Spannable string
*/ */
private static Spannable convertA(@NonNull Context context, @NonNull Account account, String text, boolean limitedToDisplayName) { private static Spannable convertA(@NonNull Context context, String text, boolean limitedToDisplayName) {
SpannableString initialContent; SpannableString initialContent;
if (text == null) { if (text == null) {
return null; return null;

View File

@ -45,6 +45,7 @@ import app.fedilab.android.R;
import app.fedilab.android.activities.ProfileActivity; import app.fedilab.android.activities.ProfileActivity;
import app.fedilab.android.client.entities.api.Account; import app.fedilab.android.client.entities.api.Account;
import app.fedilab.android.databinding.DrawerAccountBinding; import app.fedilab.android.databinding.DrawerAccountBinding;
import app.fedilab.android.helper.CustomEmoji;
import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.Helper;
import app.fedilab.android.helper.MastodonHelper; import app.fedilab.android.helper.MastodonHelper;
import app.fedilab.android.viewmodel.mastodon.AccountsVM; import app.fedilab.android.viewmodel.mastodon.AccountsVM;
@ -224,8 +225,20 @@ public class AccountAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
} }
}); });
} }
CustomEmoji.displayEmoji(context, account.emojis, account.span_display_name, accountViewHolder.binding.displayName, account.id, id -> {
if (!account.emojiFetched) {
account.emojiFetched = true;
accountViewHolder.binding.displayName.post(() -> adapter.notifyItemChanged(position));
}
});
accountViewHolder.binding.displayName.setText(account.span_display_name, TextView.BufferType.SPANNABLE); accountViewHolder.binding.displayName.setText(account.span_display_name, TextView.BufferType.SPANNABLE);
accountViewHolder.binding.username.setText(String.format("@%s", account.acct)); accountViewHolder.binding.username.setText(String.format("@%s", account.acct));
CustomEmoji.displayEmoji(context, account.emojis, account.span_note, accountViewHolder.binding.bio, account.id, id -> {
if (!account.emojiFetched) {
account.emojiFetched = true;
accountViewHolder.binding.bio.post(() -> adapter.notifyItemChanged(position));
}
});
accountViewHolder.binding.bio.setText(account.span_note, TextView.BufferType.SPANNABLE); accountViewHolder.binding.bio.setText(account.span_note, TextView.BufferType.SPANNABLE);
} }

View File

@ -44,6 +44,7 @@ import app.fedilab.android.R;
import app.fedilab.android.client.entities.api.Announcement; import app.fedilab.android.client.entities.api.Announcement;
import app.fedilab.android.client.entities.api.Reaction; import app.fedilab.android.client.entities.api.Reaction;
import app.fedilab.android.databinding.DrawerAnnouncementBinding; import app.fedilab.android.databinding.DrawerAnnouncementBinding;
import app.fedilab.android.helper.CustomEmoji;
import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.Helper;
import app.fedilab.android.viewmodel.mastodon.AnnouncementsVM; import app.fedilab.android.viewmodel.mastodon.AnnouncementsVM;
@ -87,6 +88,12 @@ public class AnnouncementAdapter extends RecyclerView.Adapter<AnnouncementAdapte
} else { } else {
holder.binding.reactionsView.setAdapter(null); holder.binding.reactionsView.setAdapter(null);
} }
CustomEmoji.displayEmoji(context, announcement.emojis, announcement.span_content, holder.binding.content, announcement.id, id -> {
if (!announcement.emojiFetched) {
announcement.emojiFetched = true;
holder.binding.content.post(() -> notifyItemChanged(position));
}
});
holder.binding.content.setText(announcement.span_content, TextView.BufferType.SPANNABLE); holder.binding.content.setText(announcement.span_content, TextView.BufferType.SPANNABLE);
if (announcement.starts_at != null) { if (announcement.starts_at != null) {
String dateIni; String dateIni;

View File

@ -103,6 +103,7 @@ import app.fedilab.android.databinding.DrawerStatusComposeBinding;
import app.fedilab.android.databinding.DrawerStatusSimpleBinding; import app.fedilab.android.databinding.DrawerStatusSimpleBinding;
import app.fedilab.android.databinding.PopupMediaDescriptionBinding; import app.fedilab.android.databinding.PopupMediaDescriptionBinding;
import app.fedilab.android.exception.DBException; import app.fedilab.android.exception.DBException;
import app.fedilab.android.helper.CustomEmoji;
import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.Helper;
import app.fedilab.android.helper.MastodonHelper; import app.fedilab.android.helper.MastodonHelper;
import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.helper.ThemeHelper;
@ -1035,12 +1036,23 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
if (getItemViewType(position) == TYPE_NORMAL) { if (getItemViewType(position) == TYPE_NORMAL) {
Status status = statusList.get(position); Status status = statusList.get(position);
StatusSimpleViewHolder holder = (StatusSimpleViewHolder) viewHolder; StatusSimpleViewHolder holder = (StatusSimpleViewHolder) viewHolder;
CustomEmoji.displayEmoji(context, status.emojis, status.span_content, holder.binding.statusContent, status.id, id -> {
if (!status.emojiFetched) {
status.emojiFetched = true;
holder.binding.statusContent.post(() -> notifyItemChanged(position));
}
});
holder.binding.statusContent.setText(status.span_content, TextView.BufferType.SPANNABLE); holder.binding.statusContent.setText(status.span_content, TextView.BufferType.SPANNABLE);
MastodonHelper.loadPPMastodon(holder.binding.avatar, status.account); MastodonHelper.loadPPMastodon(holder.binding.avatar, status.account);
CustomEmoji.displayEmoji(context, status.account.emojis, status.account.span_display_name, holder.binding.displayName, status.id, id -> {
if (!status.account.emojiFetched) {
status.account.emojiFetched = true;
holder.binding.statusContent.post(() -> notifyItemChanged(position));
}
});
holder.binding.displayName.setText(status.account.span_display_name, TextView.BufferType.SPANNABLE); holder.binding.displayName.setText(status.account.span_display_name, TextView.BufferType.SPANNABLE);
holder.binding.username.setText(String.format("@%s", status.account.acct)); holder.binding.username.setText(String.format("@%s", status.account.acct));
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(status.span_spoiler_text, TextView.BufferType.SPANNABLE); holder.binding.spoiler.setText(status.span_spoiler_text, TextView.BufferType.SPANNABLE);
} else { } else {

View File

@ -49,6 +49,7 @@ import app.fedilab.android.client.entities.api.Conversation;
import app.fedilab.android.client.entities.api.Status; import app.fedilab.android.client.entities.api.Status;
import app.fedilab.android.databinding.DrawerConversationBinding; import app.fedilab.android.databinding.DrawerConversationBinding;
import app.fedilab.android.databinding.ThumbnailBinding; import app.fedilab.android.databinding.ThumbnailBinding;
import app.fedilab.android.helper.CustomEmoji;
import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.Helper;
import app.fedilab.android.helper.MastodonHelper; import app.fedilab.android.helper.MastodonHelper;
@ -137,6 +138,12 @@ public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
notifyItemChanged(position); notifyItemChanged(position);
}); });
holder.binding.spoiler.setVisibility(View.VISIBLE); holder.binding.spoiler.setVisibility(View.VISIBLE);
CustomEmoji.displayEmoji(context, conversation.last_status.emojis, conversation.last_status.span_spoiler_text, holder.binding.spoiler, conversation.last_status.id, id -> {
if (!conversation.last_status.emojiFetched) {
conversation.last_status.emojiFetched = true;
holder.binding.spoiler.post(() -> notifyItemChanged(position));
}
});
holder.binding.spoiler.setText(conversation.last_status.span_spoiler_text, TextView.BufferType.SPANNABLE); holder.binding.spoiler.setText(conversation.last_status.span_spoiler_text, TextView.BufferType.SPANNABLE);
} else { } else {
holder.binding.spoiler.setVisibility(View.GONE); holder.binding.spoiler.setVisibility(View.GONE);
@ -144,6 +151,12 @@ public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
holder.binding.spoiler.setText(null); holder.binding.spoiler.setText(null);
} }
//--- MAIN CONTENT --- //--- MAIN CONTENT ---
CustomEmoji.displayEmoji(context, conversation.last_status.emojis, conversation.last_status.span_content, holder.binding.statusContent, conversation.last_status.id, id -> {
if (!conversation.last_status.emojiFetched) {
conversation.last_status.emojiFetched = true;
holder.binding.statusContent.post(() -> notifyItemChanged(position));
}
});
holder.binding.statusContent.setText(conversation.last_status.span_content, TextView.BufferType.SPANNABLE); holder.binding.statusContent.setText(conversation.last_status.span_content, 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

@ -24,6 +24,7 @@ import android.os.Bundle;
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 androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.app.ActivityOptionsCompat; import androidx.core.app.ActivityOptionsCompat;
@ -42,6 +43,7 @@ import app.fedilab.android.databinding.DrawerFetchMoreBinding;
import app.fedilab.android.databinding.DrawerFollowBinding; import app.fedilab.android.databinding.DrawerFollowBinding;
import app.fedilab.android.databinding.DrawerStatusNotificationBinding; import app.fedilab.android.databinding.DrawerStatusNotificationBinding;
import app.fedilab.android.databinding.NotificationsRelatedAccountsBinding; import app.fedilab.android.databinding.NotificationsRelatedAccountsBinding;
import app.fedilab.android.helper.CustomEmoji;
import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.Helper;
import app.fedilab.android.helper.MastodonHelper; import app.fedilab.android.helper.MastodonHelper;
import app.fedilab.android.viewmodel.mastodon.SearchVM; import app.fedilab.android.viewmodel.mastodon.SearchVM;
@ -120,7 +122,13 @@ public class NotificationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
if (getItemViewType(position) == TYPE_FOLLOW || getItemViewType(position) == TYPE_FOLLOW_REQUEST) { if (getItemViewType(position) == TYPE_FOLLOW || getItemViewType(position) == TYPE_FOLLOW_REQUEST) {
ViewHolderFollow holderFollow = (ViewHolderFollow) viewHolder; ViewHolderFollow holderFollow = (ViewHolderFollow) viewHolder;
MastodonHelper.loadPPMastodon(holderFollow.binding.avatar, notification.account); MastodonHelper.loadPPMastodon(holderFollow.binding.avatar, notification.account);
holderFollow.binding.displayName.setText(notification.account.display_name); CustomEmoji.displayEmoji(context, notification.account.emojis, notification.account.span_display_name, holderFollow.binding.displayName, notification.id, id -> {
if (!notification.account.emojiFetched) {
notification.account.emojiFetched = true;
holderFollow.binding.displayName.post(() -> notifyItemChanged(position));
}
});
holderFollow.binding.displayName.setText(notification.account.span_display_name, TextView.BufferType.SPANNABLE);
holderFollow.binding.username.setText(String.format("@%s", notification.account.acct)); holderFollow.binding.username.setText(String.format("@%s", notification.account.acct));
if (getItemViewType(position) == TYPE_FOLLOW_REQUEST) { if (getItemViewType(position) == TYPE_FOLLOW_REQUEST) {
holderFollow.binding.rejectButton.setVisibility(View.VISIBLE); holderFollow.binding.rejectButton.setVisibility(View.VISIBLE);
@ -188,7 +196,13 @@ public class NotificationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
} else if (getItemViewType(position) == TYPE_STATUS) { } else if (getItemViewType(position) == TYPE_STATUS) {
title = String.format(Locale.getDefault(), "%s %s", notification.account.display_name, context.getString(R.string.notif_status)); title = String.format(Locale.getDefault(), "%s %s", notification.account.display_name, context.getString(R.string.notif_status));
} }
holderStatus.bindingNotification.status.displayName.setText(title); CustomEmoji.displayEmoji(context, notification.account.emojis, notification.account.span_display_name, holderStatus.binding.displayName, notification.id, id -> {
if (!notification.account.emojiFetched) {
notification.account.emojiFetched = true;
holderStatus.binding.displayName.post(() -> notifyItemChanged(position));
}
});
holderStatus.bindingNotification.status.displayName.setText(title, TextView.BufferType.SPANNABLE);
holderStatus.bindingNotification.status.username.setText(String.format("@%s", notification.account.acct)); holderStatus.bindingNotification.status.username.setText(String.format("@%s", notification.account.acct));
holderStatus.bindingNotification.containerTransparent.setAlpha(.1f); holderStatus.bindingNotification.containerTransparent.setAlpha(.1f);
if (notification.status != null && notification.status.visibility.equalsIgnoreCase("direct")) { if (notification.status != null && notification.status.visibility.equalsIgnoreCase("direct")) {
@ -255,7 +269,13 @@ public class NotificationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
// start the new activity // start the new activity
context.startActivity(intent, options.toBundle()); context.startActivity(intent, options.toBundle());
}); });
holderStatus.bindingNotification.status.displayName.setText(title); CustomEmoji.displayEmoji(context, notification.account.emojis, notification.account.span_display_name, holderStatus.binding.displayName, notification.id, id -> {
if (!notification.account.emojiFetched) {
notification.account.emojiFetched = true;
holderStatus.binding.displayName.post(() -> notifyItemChanged(position));
}
});
holderStatus.bindingNotification.status.displayName.setText(title, TextView.BufferType.SPANNABLE);
holderStatus.bindingNotification.status.username.setText(String.format("@%s", notification.account.acct)); holderStatus.bindingNotification.status.username.setText(String.format("@%s", notification.account.acct));
holderStatus.bindingNotification.status.actionButtons.setVisibility(View.GONE); holderStatus.bindingNotification.status.actionButtons.setVisibility(View.GONE);
} }

View File

@ -750,6 +750,16 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
if (span_display_name == null || span_display_name.toString().trim().length() == 0) { if (span_display_name == null || span_display_name.toString().trim().length() == 0) {
span_display_name = new SpannableString(statusToDeal.account.username); span_display_name = new SpannableString(statusToDeal.account.username);
} }
CustomEmoji.displayEmoji(context, statusToDeal.account.emojis, span_display_name, holder.binding.displayName, status.id, id -> {
if (!statusToDeal.account.emojiFetched) {
statusToDeal.account.emojiFetched = true;
if (timelineType == Timeline.TimeLineEnum.UNKNOWN) {
return;
}
holder.binding.statusContent.post(() -> adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, id)));
}
});
holder.binding.displayName.setText(span_display_name, TextView.BufferType.SPANNABLE); holder.binding.displayName.setText(span_display_name, TextView.BufferType.SPANNABLE);
if (theme_text_header_1_line != -1) { if (theme_text_header_1_line != -1) {
holder.binding.displayName.setTextColor(theme_text_header_1_line); holder.binding.displayName.setTextColor(theme_text_header_1_line);
@ -815,6 +825,15 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
if (expand_cw || expand) { if (expand_cw || expand) {
holder.binding.spoilerExpand.setVisibility(View.VISIBLE); holder.binding.spoilerExpand.setVisibility(View.VISIBLE);
holder.binding.spoiler.setVisibility(View.VISIBLE); holder.binding.spoiler.setVisibility(View.VISIBLE);
CustomEmoji.displayEmoji(context, statusToDeal.emojis, statusToDeal.span_spoiler_text, holder.binding.spoiler, status.id, id -> {
if (!statusToDeal.emojiFetched) {
statusToDeal.emojiFetched = true;
if (timelineType == Timeline.TimeLineEnum.UNKNOWN) {
return;
}
holder.binding.statusContent.post(() -> adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, id)));
}
});
holder.binding.spoiler.setText(statusToDeal.span_spoiler_text, TextView.BufferType.SPANNABLE); holder.binding.spoiler.setText(statusToDeal.span_spoiler_text, TextView.BufferType.SPANNABLE);
statusToDeal.isExpended = true; statusToDeal.isExpended = true;
statusToDeal.isMediaDisplayed = true; statusToDeal.isMediaDisplayed = true;
@ -826,6 +845,15 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
}); });
holder.binding.spoilerExpand.setVisibility(View.VISIBLE); holder.binding.spoilerExpand.setVisibility(View.VISIBLE);
holder.binding.spoiler.setVisibility(View.VISIBLE); holder.binding.spoiler.setVisibility(View.VISIBLE);
CustomEmoji.displayEmoji(context, statusToDeal.emojis, statusToDeal.span_spoiler_text, holder.binding.spoiler, status.id, id -> {
if (!statusToDeal.emojiFetched) {
statusToDeal.emojiFetched = true;
if (timelineType == Timeline.TimeLineEnum.UNKNOWN) {
return;
}
holder.binding.statusContent.post(() -> adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, id)));
}
});
holder.binding.spoiler.setText(statusToDeal.span_spoiler_text, TextView.BufferType.SPANNABLE); holder.binding.spoiler.setText(statusToDeal.span_spoiler_text, TextView.BufferType.SPANNABLE);
} }
if (statusToDeal.isExpended) { if (statusToDeal.isExpended) {
@ -846,6 +874,15 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
if (span_display_name_boost == null || span_display_name_boost.toString().trim().length() == 0) { if (span_display_name_boost == null || span_display_name_boost.toString().trim().length() == 0) {
span_display_name_boost = new SpannableString(status.account.username); span_display_name_boost = new SpannableString(status.account.username);
} }
CustomEmoji.displayEmoji(context, statusToDeal.account.emojis, span_display_name_boost, holder.binding.statusBoosterDisplayName, status.id, id -> {
if (!statusToDeal.account.emojiFetched) {
statusToDeal.account.emojiFetched = true;
if (timelineType == Timeline.TimeLineEnum.UNKNOWN) {
return;
}
holder.binding.statusContent.post(() -> adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, id)));
}
});
holder.binding.statusBoosterDisplayName.setText(span_display_name_boost, TextView.BufferType.SPANNABLE); holder.binding.statusBoosterDisplayName.setText(span_display_name_boost, TextView.BufferType.SPANNABLE);
holder.binding.statusBoosterInfo.setVisibility(View.VISIBLE); holder.binding.statusBoosterInfo.setVisibility(View.VISIBLE);
holder.binding.boosterDivider.setVisibility(View.VISIBLE); holder.binding.boosterDivider.setVisibility(View.VISIBLE);
@ -888,7 +925,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
holder.binding.statusContent.post(() -> adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, id))); holder.binding.statusContent.post(() -> adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, id)));
} }
}); });
// CustomEmoji.displayEmoji(statusToDeal.emojis, statusToDeal.span_content, holder.binding.statusContent, null, null);
holder.binding.statusContent.setText(statusToDeal.span_content, TextView.BufferType.SPANNABLE); holder.binding.statusContent.setText(statusToDeal.span_content, 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);
@ -920,6 +957,15 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
} }
if (statusToDeal.translationContent != null) { if (statusToDeal.translationContent != null) {
holder.binding.containerTrans.setVisibility(View.VISIBLE); holder.binding.containerTrans.setVisibility(View.VISIBLE);
CustomEmoji.displayEmoji(context, statusToDeal.emojis, statusToDeal.span_translate, holder.binding.statusContentTranslated, status.id, id -> {
if (!statusToDeal.emojiFetched) {
statusToDeal.emojiFetched = true;
if (timelineType == Timeline.TimeLineEnum.UNKNOWN) {
return;
}
holder.binding.statusContent.post(() -> adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, id)));
}
});
holder.binding.statusContentTranslated.setText(statusToDeal.span_translate, TextView.BufferType.SPANNABLE); holder.binding.statusContentTranslated.setText(statusToDeal.span_translate, TextView.BufferType.SPANNABLE);
} else { } else {
holder.binding.containerTrans.setVisibility(View.GONE); holder.binding.containerTrans.setVisibility(View.GONE);
@ -1184,6 +1230,15 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
pollItemBinding.pollItemPercent.setTextColor(theme_text_color); pollItemBinding.pollItemPercent.setTextColor(theme_text_color);
pollItemBinding.pollItemText.setTextColor(theme_text_color); pollItemBinding.pollItemText.setTextColor(theme_text_color);
} }
CustomEmoji.displayEmoji(context, statusToDeal.emojis, pollItem.span_title, pollItemBinding.pollItemText, status.id, id -> {
if (!statusToDeal.emojiFetched) {
statusToDeal.emojiFetched = true;
if (timelineType == Timeline.TimeLineEnum.UNKNOWN) {
return;
}
holder.binding.statusContent.post(() -> adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, id)));
}
});
pollItemBinding.pollItemText.setText(pollItem.span_title, TextView.BufferType.SPANNABLE); pollItemBinding.pollItemText.setText(pollItem.span_title, TextView.BufferType.SPANNABLE);
pollItemBinding.pollItemValue.setProgress((int) value); pollItemBinding.pollItemValue.setProgress((int) value);
if (pollItem.votes_count == greaterValue) { if (pollItem.votes_count == greaterValue) {
@ -1212,6 +1267,15 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
for (Poll.PollItem pollOption : statusToDeal.poll.options) { for (Poll.PollItem pollOption : statusToDeal.poll.options) {
CheckBox cb = new CheckBox(context); CheckBox cb = new CheckBox(context);
cb.setButtonTintList(ThemeHelper.getButtonColorStateList(context)); cb.setButtonTintList(ThemeHelper.getButtonColorStateList(context));
CustomEmoji.displayEmoji(context, statusToDeal.emojis, pollOption.span_title, cb, status.id, id -> {
if (!statusToDeal.emojiFetched) {
statusToDeal.emojiFetched = true;
if (timelineType == Timeline.TimeLineEnum.UNKNOWN) {
return;
}
holder.binding.statusContent.post(() -> adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, id)));
}
});
cb.setText(pollOption.span_title, TextView.BufferType.SPANNABLE); cb.setText(pollOption.span_title, TextView.BufferType.SPANNABLE);
holder.binding.poll.multipleChoice.addView(cb); holder.binding.poll.multipleChoice.addView(cb);
} }
@ -1223,6 +1287,24 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
for (Poll.PollItem pollOption : statusToDeal.poll.options) { for (Poll.PollItem pollOption : statusToDeal.poll.options) {
RadioButton rb = new RadioButton(context); RadioButton rb = new RadioButton(context);
rb.setButtonTintList(ThemeHelper.getButtonColorStateList(context)); rb.setButtonTintList(ThemeHelper.getButtonColorStateList(context));
CustomEmoji.displayEmoji(context, statusToDeal.account.emojis, pollOption.span_title, rb, status.id, id -> {
if (!statusToDeal.account.emojiFetched) {
statusToDeal.account.emojiFetched = true;
if (timelineType == Timeline.TimeLineEnum.UNKNOWN) {
return;
}
holder.binding.statusContent.post(() -> adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, id)));
}
});
CustomEmoji.displayEmoji(context, statusToDeal.emojis, pollOption.span_title, rb, status.id, id -> {
if (!statusToDeal.emojiFetched) {
statusToDeal.emojiFetched = true;
if (timelineType == Timeline.TimeLineEnum.UNKNOWN) {
return;
}
holder.binding.statusContent.post(() -> adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, id)));
}
});
rb.setText(pollOption.span_title, TextView.BufferType.SPANNABLE); rb.setText(pollOption.span_title, TextView.BufferType.SPANNABLE);
holder.binding.poll.singleChoiceRadioGroup.addView(rb); holder.binding.poll.singleChoiceRadioGroup.addView(rb);
} }
@ -1827,6 +1909,15 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
.load(status.art_attachment.preview_url) .load(status.art_attachment.preview_url)
.apply(new RequestOptions().transform(new RoundedCorners((int) Helper.convertDpToPixel(3, context)))) .apply(new RequestOptions().transform(new RoundedCorners((int) Helper.convertDpToPixel(3, context))))
.into(holder.bindingArt.artMedia); .into(holder.bindingArt.artMedia);
CustomEmoji.displayEmoji(context, status.emojis, status.account.span_display_name, holder.bindingArt.artAcct, status.id, id -> {
if (!status.emojiFetched) {
status.emojiFetched = true;
if (timelineType == Timeline.TimeLineEnum.UNKNOWN) {
return;
}
notifyItemChanged(getPositionAsync(null, statusList, id));
}
});
holder.bindingArt.artAcct.setText(status.account.span_display_name, TextView.BufferType.SPANNABLE); holder.bindingArt.artAcct.setText(status.account.span_display_name, TextView.BufferType.SPANNABLE);
holder.bindingArt.artUsername.setText(String.format(Locale.getDefault(), "@%s", status.account.acct)); holder.bindingArt.artUsername.setText(String.format(Locale.getDefault(), "@%s", status.account.acct));
holder.bindingArt.artPp.setOnClickListener(v -> { holder.bindingArt.artPp.setOnClickListener(v -> {

View File

@ -232,7 +232,7 @@ public class TimelinesVM extends AndroidViewModel {
statusList.add(status); statusList.add(status);
} }
} }
statuses.statuses = SpannableHelper.convertNitterStatus(getApplication().getApplicationContext(), statusList); statuses.statuses = SpannableHelper.convertNitterStatus(statusList);
String max_id = publicTlResponse.headers().get("min-id"); String max_id = publicTlResponse.headers().get("min-id");
statuses.pagination = new Pagination(); statuses.pagination = new Pagination();
statuses.pagination.max_id = max_id; statuses.pagination.max_id = max_id;