text emoji fix

This commit is contained in:
nuclearfog 2023-04-15 17:09:39 +02:00
parent aa283b983f
commit 799e5568fa
No known key found for this signature in database
GPG Key ID: 03488A185C476379
5 changed files with 63 additions and 20 deletions

View File

@ -17,11 +17,15 @@ import java.util.regex.Pattern;
* *
* @author nuclearfog * @author nuclearfog
*/ */
public class TextWithEmoji { public class EmojiUtils {
/**
* emoji pattern used by Mastodon
*/
private static final Pattern EMOJI_PATTERN = Pattern.compile(":\\w+:"); private static final Pattern EMOJI_PATTERN = Pattern.compile(":\\w+:");
private TextWithEmoji() {}
private EmojiUtils() {}
/** /**
* replace tags with emojis * replace tags with emojis
@ -31,16 +35,14 @@ public class TextWithEmoji {
*/ */
public static Spannable addEmojis(Context context, Spannable spannable, Map<String, Bitmap> emojis) { public static Spannable addEmojis(Context context, Spannable spannable, Map<String, Bitmap> emojis) {
if (spannable.length() > 0 && !emojis.isEmpty()) { if (spannable.length() > 0 && !emojis.isEmpty()) {
SpannableStringBuilder builder = new SpannableStringBuilder(spannable); Stack<Integer> indexes = getTagIndexes(spannable);
Matcher matcher = EMOJI_PATTERN.matcher(spannable); if (indexes.isEmpty()) {
Stack<Integer> indexes = new Stack<>(); return spannable;
while (matcher.find()) {
indexes.push(matcher.start());
indexes.push(matcher.end());
} }
SpannableStringBuilder builder = new SpannableStringBuilder(spannable);
while (!indexes.isEmpty()) { while (!indexes.isEmpty()) {
int end = indexes.pop();
int start = indexes.pop(); int start = indexes.pop();
int end = indexes.pop();
String tag = builder.subSequence(start + 1, end - 1).toString(); String tag = builder.subSequence(start + 1, end - 1).toString();
Bitmap emoji = emojis.get(tag); Bitmap emoji = emojis.get(tag);
if (emoji != null) { if (emoji != null) {
@ -54,4 +56,39 @@ public class TextWithEmoji {
} }
return spannable; return spannable;
} }
/**
* remove emoji tags from spannable
*/
public static Spannable removeTags(Spannable spannable) {
if (spannable.length() > 0) {
Stack<Integer> indexes = getTagIndexes(spannable);
if (!indexes.isEmpty()) {
SpannableStringBuilder builder = new SpannableStringBuilder(spannable);
while (!indexes.isEmpty()) {
int start = indexes.pop();
int end = indexes.pop();
builder.delete(start, end);
}
return builder;
}
}
return spannable;
}
/**
* create a stack with indexes of emoji tags
*
* @param spannable spannable containing emoji tags
* @return indexes stack
*/
private static Stack<Integer> getTagIndexes(Spannable spannable) {
Matcher matcher = EMOJI_PATTERN.matcher(spannable);
Stack<Integer> indexes = new Stack<>();
while (matcher.find()) {
indexes.push(matcher.end());
indexes.push(matcher.start());
}
return indexes;
}
} }

View File

@ -74,7 +74,7 @@ import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler; import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.backend.image.PicassoBuilder; import org.nuclearfog.twidda.backend.image.PicassoBuilder;
import org.nuclearfog.twidda.backend.utils.StringUtils; import org.nuclearfog.twidda.backend.utils.StringUtils;
import org.nuclearfog.twidda.backend.utils.TextWithEmoji; import org.nuclearfog.twidda.backend.utils.EmojiUtils;
import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.Relation; import org.nuclearfog.twidda.model.Relation;
import org.nuclearfog.twidda.model.User; import org.nuclearfog.twidda.model.User;
@ -765,6 +765,9 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
} }
if (!user.getDescription().isEmpty()) { if (!user.getDescription().isEmpty()) {
descriptionSpan = Tagger.makeTextWithLinks(user.getDescription(), settings.getHighlightColor(), this); descriptionSpan = Tagger.makeTextWithLinks(user.getDescription(), settings.getHighlightColor(), this);
if (user.getEmojis().length > 0) {
descriptionSpan = EmojiUtils.removeTags(descriptionSpan);
}
description.setText(descriptionSpan); description.setText(descriptionSpan);
description.setVisibility(VISIBLE); description.setVisibility(VISIBLE);
} else { } else {
@ -834,7 +837,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
*/ */
private void onUsernameUpdate(@NonNull EmojiResult result) { private void onUsernameUpdate(@NonNull EmojiResult result) {
if (result.images != null) { if (result.images != null) {
Spannable spannable = TextWithEmoji.addEmojis(getApplicationContext(), result.spannable, result.images); Spannable spannable = EmojiUtils.addEmojis(getApplicationContext(), result.spannable, result.images);
username.setText(spannable); username.setText(spannable);
} }
} }
@ -844,7 +847,7 @@ public class ProfileActivity extends AppCompatActivity implements ActivityResult
*/ */
private void onUserDescriptionUpdate(@NonNull EmojiResult result) { private void onUserDescriptionUpdate(@NonNull EmojiResult result) {
if (result.images != null) { if (result.images != null) {
Spannable spannable = TextWithEmoji.addEmojis(getApplicationContext(), result.spannable, result.images); Spannable spannable = EmojiUtils.addEmojis(getApplicationContext(), result.spannable, result.images);
description.setText(spannable); description.setText(spannable);
} }
} }

View File

@ -71,7 +71,7 @@ import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler; import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.backend.image.PicassoBuilder; import org.nuclearfog.twidda.backend.image.PicassoBuilder;
import org.nuclearfog.twidda.backend.utils.StringUtils; import org.nuclearfog.twidda.backend.utils.StringUtils;
import org.nuclearfog.twidda.backend.utils.TextWithEmoji; import org.nuclearfog.twidda.backend.utils.EmojiUtils;
import org.nuclearfog.twidda.config.Configuration; import org.nuclearfog.twidda.config.Configuration;
import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.Card; import org.nuclearfog.twidda.model.Card;
@ -1141,7 +1141,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
*/ */
private void onStatusTextUpdate(@NonNull EmojiResult result) { private void onStatusTextUpdate(@NonNull EmojiResult result) {
if (settings.getLogin().getConfiguration() == Configuration.MASTODON && result.images != null) { if (settings.getLogin().getConfiguration() == Configuration.MASTODON && result.images != null) {
Spannable spannable = TextWithEmoji.addEmojis(getApplicationContext(), result.spannable, result.images); Spannable spannable = EmojiUtils.addEmojis(getApplicationContext(), result.spannable, result.images);
statusText.setText(spannable); statusText.setText(spannable);
} }
} }
@ -1151,7 +1151,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
*/ */
private void onUsernameUpdate(@NonNull EmojiResult result) { private void onUsernameUpdate(@NonNull EmojiResult result) {
if (settings.getLogin().getConfiguration() == Configuration.MASTODON && result.images != null) { if (settings.getLogin().getConfiguration() == Configuration.MASTODON && result.images != null) {
Spannable spannable = TextWithEmoji.addEmojis(getApplicationContext(), result.spannable, result.images); Spannable spannable = EmojiUtils.addEmojis(getApplicationContext(), result.spannable, result.images);
username.setText(spannable); username.setText(spannable);
} }
} }

View File

@ -32,7 +32,7 @@ import org.nuclearfog.twidda.backend.async.EmojiLoader.EmojiParam;
import org.nuclearfog.twidda.backend.async.EmojiLoader.EmojiResult; import org.nuclearfog.twidda.backend.async.EmojiLoader.EmojiResult;
import org.nuclearfog.twidda.backend.utils.AppStyles; import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.StringUtils; import org.nuclearfog.twidda.backend.utils.StringUtils;
import org.nuclearfog.twidda.backend.utils.TextWithEmoji; import org.nuclearfog.twidda.backend.utils.EmojiUtils;
import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.Notification; import org.nuclearfog.twidda.model.Notification;
import org.nuclearfog.twidda.model.Status; import org.nuclearfog.twidda.model.Status;
@ -155,6 +155,9 @@ public class StatusHolder extends ViewHolder implements OnClickListener {
created.setText(StringUtils.formatCreationTime(itemView.getResources(), status.getTimestamp())); created.setText(StringUtils.formatCreationTime(itemView.getResources(), status.getTimestamp()));
if (!status.getText().trim().isEmpty()) { if (!status.getText().trim().isEmpty()) {
textSpan = Tagger.makeTextWithLinks(status.getText(), settings.getHighlightColor()); textSpan = Tagger.makeTextWithLinks(status.getText(), settings.getHighlightColor());
if (status.getEmojis().length > 0) {
textSpan = EmojiUtils.removeTags(textSpan);
}
statusText.setText(textSpan); statusText.setText(textSpan);
statusText.setVisibility(View.VISIBLE); statusText.setVisibility(View.VISIBLE);
} else { } else {
@ -288,7 +291,7 @@ public class StatusHolder extends ViewHolder implements OnClickListener {
*/ */
private void setUsernameEmojis(@NonNull EmojiResult result) { private void setUsernameEmojis(@NonNull EmojiResult result) {
if (result.id == tagId && result.images != null) { if (result.id == tagId && result.images != null) {
Spannable spannable = TextWithEmoji.addEmojis(username.getContext(), result.spannable, result.images); Spannable spannable = EmojiUtils.addEmojis(username.getContext(), result.spannable, result.images);
username.setText(spannable); username.setText(spannable);
} }
} }
@ -300,7 +303,7 @@ public class StatusHolder extends ViewHolder implements OnClickListener {
*/ */
private void setTextEmojis(@NonNull EmojiResult result) { private void setTextEmojis(@NonNull EmojiResult result) {
if (result.id == tagId && result.images != null) { if (result.id == tagId && result.images != null) {
Spannable spannable = TextWithEmoji.addEmojis(statusText.getContext(), result.spannable, result.images); Spannable spannable = EmojiUtils.addEmojis(statusText.getContext(), result.spannable, result.images);
statusText.setText(spannable); statusText.setText(spannable);
} }
} }

View File

@ -30,7 +30,7 @@ import org.nuclearfog.twidda.backend.async.EmojiLoader.EmojiParam;
import org.nuclearfog.twidda.backend.async.EmojiLoader.EmojiResult; import org.nuclearfog.twidda.backend.async.EmojiLoader.EmojiResult;
import org.nuclearfog.twidda.backend.utils.AppStyles; import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.StringUtils; import org.nuclearfog.twidda.backend.utils.StringUtils;
import org.nuclearfog.twidda.backend.utils.TextWithEmoji; import org.nuclearfog.twidda.backend.utils.EmojiUtils;
import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.config.GlobalSettings;
import org.nuclearfog.twidda.model.Notification; import org.nuclearfog.twidda.model.Notification;
import org.nuclearfog.twidda.model.User; import org.nuclearfog.twidda.model.User;
@ -110,7 +110,7 @@ public class UserHolder extends ViewHolder implements OnClickListener, AsyncCall
@Override @Override
public void onResult(@NonNull EmojiResult result) { public void onResult(@NonNull EmojiResult result) {
if (result.id == tagId && result.images != null) { if (result.id == tagId && result.images != null) {
Spannable spannable = TextWithEmoji.addEmojis(username.getContext(), result.spannable, result.images); Spannable spannable = EmojiUtils.addEmojis(username.getContext(), result.spannable, result.images);
username.setText(spannable); username.setText(spannable);
} }
} }