diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 6a5c9cbb8c..12d1a43375 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -41,13 +41,6 @@
-
-
-
-
-
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java
index 1abee7029b..3a8ef3ff92 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java
@@ -36,7 +36,6 @@ import org.thoughtcrime.securesms.components.mention.MentionRendererDelegate;
import org.thoughtcrime.securesms.components.spoiler.SpoilerRendererDelegate;
import org.thoughtcrime.securesms.emoji.JumboEmoji;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
-import org.thoughtcrime.securesms.util.SpoilerFilteringSpannable;
import org.thoughtcrime.securesms.util.Util;
import java.util.Arrays;
@@ -110,7 +109,7 @@ public class EmojiTextView extends AppCompatTextView {
}
public void enableSpoilerFiltering() {
- spoilerFilteringSpannableFactory = new SpoilerFilteringSpannableFactory();
+ spoilerFilteringSpannableFactory = new SpoilerFilteringSpannableFactory(() -> isInOnDraw);
setSpannableFactory(spoilerFilteringSpannableFactory);
}
@@ -454,15 +453,4 @@ public class EmojiTextView extends AppCompatTextView {
mentionRendererDelegate.setTint(mentionBackgroundTint);
}
}
-
- private class SpoilerFilteringSpannableFactory extends Spannable.Factory {
- @Override
- public @NonNull Spannable newSpannable(CharSequence source) {
- return wrap(super.newSpannable(source));
- }
-
- @NonNull SpoilerFilteringSpannable wrap(Spannable source) {
- return new SpoilerFilteringSpannable(source, () -> isInOnDraw);
- }
- }
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SimpleEmojiTextView.kt b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SimpleEmojiTextView.kt
index 6ee69a1f85..8d5efdfdb4 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SimpleEmojiTextView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SimpleEmojiTextView.kt
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.components.emoji
import android.content.Context
import android.graphics.Canvas
+import android.text.Spannable
import android.text.Spanned
import android.text.TextUtils
import android.util.AttributeSet
@@ -20,6 +21,8 @@ open class SimpleEmojiTextView @JvmOverloads constructor(
private var bufferType: BufferType? = null
private val sizeChangeDebouncer: ThrottledDebouncer = ThrottledDebouncer(200)
private val spoilerRendererDelegate: SpoilerRendererDelegate
+ private var spoilerFilteringSpannableFactory: SpoilerFilteringSpannableFactory? = null
+ private var isInOnDraw: Boolean = false
init {
isEmojiCompatEnabled = isInEditMode || SignalStore.settings().isPreferSystemEmoji
@@ -27,6 +30,8 @@ open class SimpleEmojiTextView @JvmOverloads constructor(
}
override fun onDraw(canvas: Canvas) {
+ isInOnDraw = true
+
if (text is Spanned && layout != null) {
val checkpoint = canvas.save()
canvas.translate(totalPaddingLeft.toFloat(), totalPaddingTop.toFloat())
@@ -37,6 +42,8 @@ open class SimpleEmojiTextView @JvmOverloads constructor(
}
}
super.onDraw(canvas)
+
+ isInOnDraw = false
}
override fun setText(text: CharSequence?, type: BufferType?) {
@@ -56,11 +63,16 @@ open class SimpleEmojiTextView @JvmOverloads constructor(
EmojiProvider.emojify(newCandidates, text, this, false)
}
- val newContent = if (width == 0 || maxLines == -1) {
+ var newContent: CharSequence? = if (width == 0 || maxLines == -1) {
newText
} else {
TextUtils.ellipsize(newText, paint, (adjustedWidth * maxLines).toFloat(), TextUtils.TruncateAt.END, false, null)
}
+
+ if (newContent is Spannable && spoilerFilteringSpannableFactory != null) {
+ newContent = spoilerFilteringSpannableFactory!!.wrap(newContent)
+ }
+
bufferType = BufferType.SPANNABLE
super.setText(newContent, type)
}
@@ -74,4 +86,9 @@ open class SimpleEmojiTextView @JvmOverloads constructor(
}
}
}
+
+ fun enableSpoilerFiltering() {
+ spoilerFilteringSpannableFactory = SpoilerFilteringSpannableFactory { isInOnDraw }
+ setSpannableFactory(spoilerFilteringSpannableFactory!!)
+ }
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SpoilerFilteringSpannableFactory.kt b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SpoilerFilteringSpannableFactory.kt
new file mode 100644
index 0000000000..5e8230f70c
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SpoilerFilteringSpannableFactory.kt
@@ -0,0 +1,21 @@
+package org.thoughtcrime.securesms.components.emoji
+
+import android.text.Spannable
+import org.thoughtcrime.securesms.util.SpoilerFilteringSpannable
+import org.thoughtcrime.securesms.util.SpoilerFilteringSpannable.InOnDrawProvider
+
+/**
+ * Spannable factory used to help ensure spans are copied/maintained properly through the
+ * Android text handling system.
+ *
+ * @param inOnDraw Used by [SpoilerFilteringSpannable] to remove spans when being called from onDraw
+ */
+class SpoilerFilteringSpannableFactory(private val inOnDraw: InOnDrawProvider) : Spannable.Factory() {
+ override fun newSpannable(source: CharSequence): Spannable {
+ return wrap(super.newSpannable(source))
+ }
+
+ fun wrap(source: Spannable): SpoilerFilteringSpannable {
+ return SpoilerFilteringSpannable(source, inOnDraw)
+ }
+}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java
index 4d51ddebcd..d28386d2a0 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListItem.java
@@ -60,6 +60,7 @@ import org.thoughtcrime.securesms.components.DeliveryStatusView;
import org.thoughtcrime.securesms.components.FromTextView;
import org.thoughtcrime.securesms.components.TypingIndicatorView;
import org.thoughtcrime.securesms.components.emoji.EmojiStrings;
+import org.thoughtcrime.securesms.components.emoji.SimpleEmojiTextView;
import org.thoughtcrime.securesms.contacts.paged.ContactSearchData;
import org.thoughtcrime.securesms.conversation.MessageStyler;
import org.thoughtcrime.securesms.conversationlist.model.ConversationSet;
@@ -113,7 +114,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
private LiveRecipient recipient;
private long threadId;
private GlideRequests glideRequests;
- private TextView subjectView;
+ private SimpleEmojiTextView subjectView;
private TypingIndicatorView typingView;
private FromTextView fromView;
private TextView dateView;
@@ -170,6 +171,8 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
this.thumbTarget = new GlideLiveDataTarget(thumbSize, thumbSize);
this.searchStyleFactory = () -> new CharacterStyle[] { new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.signal_colorOnSurface)), SpanUtil.getBoldSpan() };
+ this.subjectView.enableSpoilerFiltering();
+
getLayoutTransition().setDuration(150);
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SpoilerFilteringSpannable.kt b/app/src/main/java/org/thoughtcrime/securesms/util/SpoilerFilteringSpannable.kt
index 950dab5a7b..e444ddb2ab 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/util/SpoilerFilteringSpannable.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/SpoilerFilteringSpannable.kt
@@ -69,7 +69,7 @@ class SpoilerFilteringSpannable(private val spannable: Spannable, private val in
override fun hashCode(): Int = spannable.hashCode()
override fun equals(other: Any?): Boolean = spannable == other
- interface InOnDrawProvider {
+ fun interface InOnDrawProvider {
fun isInOnDraw(): Boolean
}
}