From 9802724baae302a0eecbfd13839e97ca0a8c8b8f Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Wed, 9 Feb 2022 16:08:21 -0500 Subject: [PATCH] Don't shorten message footers for mixed-direction text. --- .../conversation/ConversationItem.java | 1 + .../securesms/util/StringUtil.java | 26 ++++++++++ .../StringUtilTest_hasMixedTextDirection.java | 49 +++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 app/src/test/java/org/thoughtcrime/securesms/util/StringUtilTest_hasMixedTextDirection.java diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java index bdf8552b00..5cbb70504b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java @@ -457,6 +457,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo isFooterVisible(messageRecord, nextMessageRecord, groupThread) && !bodyText.isJumbomoji() && conversationMessage.getBottomButton() == null && + !StringUtil.hasMixedTextDirection(bodyText.getText()) && bodyText.getLastLineWidth() > 0) { TextView dateView = footer.getDateView(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/StringUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/StringUtil.java index 4e244d5d46..bb52699cda 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/StringUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/StringUtil.java @@ -168,6 +168,32 @@ public final class StringUtil { return new String(Character.toChars(codePoint)); } + /** + * @return True if the provided text contains a mix of LTR and RTL characters, otherwise false. + */ + public static boolean hasMixedTextDirection(@Nullable CharSequence text) { + if (text == null) { + return false; + } + + Boolean isLtr = null; + + for (int i = 0, len = Character.codePointCount(text, 0, text.length()); i < len; i++) { + int codePoint = Character.codePointAt(text, i); + byte direction = Character.getDirectionality(codePoint); + + if (isLtr != null && isLtr && direction != Character.DIRECTIONALITY_LEFT_TO_RIGHT) { + return true; + } else if (isLtr != null && !isLtr && direction != Character.DIRECTIONALITY_RIGHT_TO_LEFT) { + return true; + } else { + isLtr = direction == Character.DIRECTIONALITY_LEFT_TO_RIGHT; + } + } + + return false; + } + /** * Isolates bi-directional text from influencing surrounding text. You should use this whenever * you're injecting user-generated text into a larger string. diff --git a/app/src/test/java/org/thoughtcrime/securesms/util/StringUtilTest_hasMixedTextDirection.java b/app/src/test/java/org/thoughtcrime/securesms/util/StringUtilTest_hasMixedTextDirection.java new file mode 100644 index 0000000000..7701480675 --- /dev/null +++ b/app/src/test/java/org/thoughtcrime/securesms/util/StringUtilTest_hasMixedTextDirection.java @@ -0,0 +1,49 @@ +package org.thoughtcrime.securesms.util; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +public final class StringUtilTest_hasMixedTextDirection { + + private final CharSequence input; + private final boolean expected; + + @Parameterized.Parameters + public static Collection data() { + return Arrays.asList(new Object[][]{ + { "", false }, + { null, false }, + { "A", false}, + { "ة", false}, // Arabic + { "ی", false}, // Kurdish + { "ی", false }, // Farsi + { "و", false }, // Urdu + { "ת", false }, // Hebrew + { "ש", false }, // Yiddish + { "Aة", true }, // Arabic-ASCII + { "یA", true }, // Kurdish-ASCII + { "Aی", true }, // Farsi-ASCII + { "وA", true }, // Urdu-ASCII + { "Aת", true }, // Hebrew-ASCII + { "שA", true }, // Yiddish-ASCII + }); + } + + public StringUtilTest_hasMixedTextDirection(CharSequence input, boolean expected) { + this.input = input; + this.expected = expected; + } + + @Test + public void trim() { + boolean output = StringUtil.hasMixedTextDirection(input); + assertEquals(expected, output); + } +}