Add additional text formatting support.

This commit is contained in:
Cody Henthorne
2023-03-20 12:24:52 -04:00
committed by Greyson Parrelli
parent 1c3636eedd
commit 25028e0e6f
11 changed files with 155 additions and 44 deletions

View File

@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.text.Annotation;
@@ -17,9 +16,6 @@ import android.text.TextUtils;
import android.text.TextUtils.TruncateAt;
import android.text.style.CharacterStyle;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.TypefaceSpan;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.Menu;
@@ -63,7 +59,6 @@ import static org.thoughtcrime.securesms.database.MentionUtil.MENTION_STARTER;
public class ComposeText extends EmojiEditText {
private static final char EMOJI_STARTER = ':';
private static final long EMOJI_KEYWORD_DELAY = 1500;
private static final Pattern TIME_PATTERN = Pattern.compile("^[0-9]{1,2}:[0-9]{1,2}$");
@@ -76,13 +71,6 @@ public class ComposeText extends EmojiEditText {
@Nullable private CursorPositionChangedListener cursorPositionChangedListener;
@Nullable private InlineQueryChangedListener inlineQueryChangedListener;
private final Runnable keywordSearchRunnable = () -> {
Editable text = getText();
if (text != null && enoughToFilter(text, true)) {
performFiltering(text, true);
}
};
public ComposeText(Context context) {
super(context);
initialize();
@@ -362,7 +350,7 @@ public class ComposeText extends EmojiEditText {
}
if (style != null) {
replacement.setSpan(style, 0, charSequence.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
replacement.setSpan(style, 0, charSequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
clearComposingText();
@@ -532,6 +520,11 @@ public class ComposeText extends EmojiEditText {
return -1;
}
@Override
protected boolean shouldPersistSignalStylingWhenPasting() {
return true;
}
/**
* Return true if we think the user may be inputting a time.
*/

View File

@@ -1,9 +1,13 @@
package org.thoughtcrime.securesms.components.emoji;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.InputFilter;
import android.text.TextUtils;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
@@ -14,7 +18,9 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.emoji.EmojiProvider.EmojiDrawable;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.EditTextExtensionsKt;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import java.util.HashSet;
import java.util.Set;
@@ -35,9 +41,9 @@ public class EmojiEditText extends AppCompatEditText {
public EmojiEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.EmojiTextView, 0, 0);
boolean forceCustom = a.getBoolean(R.styleable.EmojiTextView_emoji_forceCustom, false);
boolean jumboEmoji = a.getBoolean(R.styleable.EmojiTextView_emoji_forceJumbo, false);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.EmojiTextView, 0, 0);
boolean forceCustom = a.getBoolean(R.styleable.EmojiTextView_emoji_forceCustom, false);
boolean jumboEmoji = a.getBoolean(R.styleable.EmojiTextView_emoji_forceJumbo, false);
a.recycle();
if (!isInEditMode() && (forceCustom || !SignalStore.settings().isPreferSystemEmoji())) {
@@ -57,8 +63,8 @@ public class EmojiEditText extends AppCompatEditText {
}
public void insertEmoji(String emoji) {
final int start = getSelectionStart();
final int end = getSelectionEnd();
final int start = getSelectionStart();
final int end = getSelectionEnd();
getText().replace(Math.min(start, end), Math.max(start, end), emoji);
setSelection(start + emoji.length());
@@ -66,8 +72,11 @@ public class EmojiEditText extends AppCompatEditText {
@Override
public void invalidateDrawable(@NonNull Drawable drawable) {
if (drawable instanceof EmojiDrawable) invalidate();
else super.invalidateDrawable(drawable);
if (drawable instanceof EmojiDrawable) {
invalidate();
} else {
super.invalidateDrawable(drawable);
}
}
@Override
@@ -95,4 +104,50 @@ public class EmojiEditText extends AppCompatEditText {
return result;
}
@Override
public boolean onTextContextMenuItem(int id) {
if (id == android.R.id.paste) {
ClipData clipData = ServiceUtil.getClipboardManager(getContext()).getPrimaryClip();
if (clipData != null) {
CharSequence label = clipData.getDescription().getLabel();
CharSequence pendingPaste = getTextFromClipData(clipData);
if (TextUtils.equals(Util.COPY_LABEL, label) && shouldPersistSignalStylingWhenPasting()) {
return super.onTextContextMenuItem(id);
} else if (Build.VERSION.SDK_INT >= 23) {
return super.onTextContextMenuItem(android.R.id.pasteAsPlainText);
} else if (pendingPaste != null) {
Util.copyToClipboard(getContext(), pendingPaste.toString());
return super.onTextContextMenuItem(id);
}
}
} else if (id == android.R.id.copy || id == android.R.id.cut) {
boolean originalResult = super.onTextContextMenuItem(id);
ClipboardManager clipboardManager = ServiceUtil.getClipboardManager(getContext());
CharSequence clipText = getTextFromClipData(clipboardManager.getPrimaryClip());
if (clipText != null) {
Util.copyToClipboard(getContext(), clipText);
return true;
}
return originalResult;
}
return super.onTextContextMenuItem(id);
}
private @Nullable CharSequence getTextFromClipData(@Nullable ClipData data) {
if (data != null && data.getItemCount() > 0) {
return data.getItemAt(0).coerceToText(getContext());
} else {
return null;
}
}
protected boolean shouldPersistSignalStylingWhenPasting() {
return false;
}
}