diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/FromTextView.java b/app/src/main/java/org/thoughtcrime/securesms/components/FromTextView.java index a0475e709e..ae013da007 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/FromTextView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/FromTextView.java @@ -5,10 +5,14 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.os.Build; import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; +import android.text.style.CharacterStyle; +import android.text.style.MetricAffectingSpan; import android.text.style.StyleSpan; +import android.text.style.TypefaceSpan; import android.util.AttributeSet; import androidx.annotation.Nullable; @@ -17,15 +21,20 @@ import androidx.core.content.ContextCompat; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.components.emoji.EmojiTextView; +import org.thoughtcrime.securesms.components.emoji.SimpleEmojiTextView; import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.util.SpanUtil; import org.thoughtcrime.securesms.util.ViewUtil; import java.util.Objects; -public class FromTextView extends EmojiTextView { +public class FromTextView extends SimpleEmojiTextView { private static final String TAG = Log.tag(FromTextView.class); + private final static Typeface BOLD_TYPEFACE = Typeface.create("sans-serif-medium", Typeface.NORMAL); + private final static Typeface LIGHT_TYPEFACE = Typeface.create("sans-serif", Typeface.NORMAL); + public FromTextView(Context context) { super(context); } @@ -45,20 +54,9 @@ public class FromTextView extends EmojiTextView { public void setText(Recipient recipient, boolean read, @Nullable String suffix) { String fromString = recipient.getDisplayName(getContext()); - int typeface; - - if (!read) { - typeface = Typeface.BOLD; - } else { - typeface = Typeface.NORMAL; - } - - SpannableStringBuilder builder = new SpannableStringBuilder(); - - SpannableString fromSpan = new SpannableString(fromString); - fromSpan.setSpan(new StyleSpan(typeface), 0, builder.length(), - Spannable.SPAN_INCLUSIVE_EXCLUSIVE); - + SpannableStringBuilder builder = new SpannableStringBuilder(); + SpannableString fromSpan = new SpannableString(fromString); + fromSpan.setSpan(getFontSpan(!read), 0, fromSpan.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); if (recipient.isSelf()) { builder.append(getContext().getString(R.string.note_to_self)); @@ -85,4 +83,8 @@ public class FromTextView extends EmojiTextView { return mutedDrawable; } + + private CharacterStyle getFontSpan(boolean isBold) { + return isBold ? SpanUtil.getBoldSpan() : SpanUtil.getNormalSpan(); + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SingleLineEmojiTextView.kt b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SimpleEmojiTextView.kt similarity index 79% rename from app/src/main/java/org/thoughtcrime/securesms/components/emoji/SingleLineEmojiTextView.kt rename to app/src/main/java/org/thoughtcrime/securesms/components/emoji/SimpleEmojiTextView.kt index cf833c6ef2..e8813f1a7a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SingleLineEmojiTextView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/SimpleEmojiTextView.kt @@ -7,7 +7,7 @@ import androidx.appcompat.widget.AppCompatTextView import org.thoughtcrime.securesms.keyvalue.SignalStore import org.whispersystems.libsignal.util.guava.Optional -open class SingleLineEmojiTextView @JvmOverloads constructor( +open class SimpleEmojiTextView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 @@ -15,20 +15,16 @@ open class SingleLineEmojiTextView @JvmOverloads constructor( private var bufferType: BufferType? = null - init { - maxLines = 1 - } - override fun setText(text: CharSequence?, type: BufferType?) { bufferType = type val candidates = if (isInEditMode) null else EmojiProvider.getCandidates(text) if (SignalStore.settings().isPreferSystemEmoji || candidates == null || candidates.size() == 0) { super.setText(Optional.fromNullable(text).or(""), BufferType.NORMAL) } else { - val newContent = if (width == 0) { + val newContent = if (width == 0 || maxLines == -1) { text } else { - TextUtils.ellipsize(text, paint, width.toFloat(), TextUtils.TruncateAt.END, false, null) + TextUtils.ellipsize(text, paint, (width * maxLines).toFloat(), TextUtils.TruncateAt.END, false, null) } val newCandidates = if (isInEditMode) null else EmojiProvider.getCandidates(newContent) @@ -47,9 +43,4 @@ open class SingleLineEmojiTextView @JvmOverloads constructor( setText(text, bufferType ?: BufferType.NORMAL) } } - - override fun setMaxLines(maxLines: Int) { - check(maxLines == 1) { "setMaxLines: $maxLines != 1" } - super.setMaxLines(maxLines) - } } 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 3884bd802e..b79e16d629 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java @@ -836,8 +836,8 @@ public final class ConversationItem extends RelativeLayout implements BindableCo if (messageRequestAccepted) { linkifyMessageBody(styledText, batchSelected.isEmpty()); } - styledText = SearchUtil.getHighlightedSpan(locale, () -> new BackgroundColorSpan(Color.YELLOW), styledText, searchQuery); - styledText = SearchUtil.getHighlightedSpan(locale, () -> new ForegroundColorSpan(Color.BLACK), styledText, searchQuery); + styledText = SearchUtil.getHighlightedSpan(locale, () -> new BackgroundColorSpan(Color.YELLOW), styledText, searchQuery, SearchUtil.STRICT); + styledText = SearchUtil.getHighlightedSpan(locale, () -> new ForegroundColorSpan(Color.BLACK), styledText, searchQuery, SearchUtil.STRICT); if (hasExtraText(messageRecord)) { bodyText.setOverflowText(getLongMessageSpan(messageRecord)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListAdapter.java index 2644fa7698..f1e5fdf4c4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListAdapter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListAdapter.java @@ -101,7 +101,7 @@ class ConversationListAdapter extends ListAdapter new StyleSpan(Typeface.BOLD), name, highlightSubstring)); + this.fromView.setText(SearchUtil.getHighlightedSpan(locale, SpanUtil::getBoldSpan, name, highlightSubstring, SearchUtil.MATCH_ALL)); } else { this.fromView.setText(recipient.get(), thread.isRead()); } @@ -178,10 +182,6 @@ public final class ConversationListItem extends ConstraintLayout observeDisplayBody(getThreadDisplayBody(getContext(), thread)); - this.subjectView.setTypeface(thread.isRead() ? LIGHT_TYPEFACE : BOLD_TYPEFACE); - this.subjectView.setTextColor(thread.isRead() ? ContextCompat.getColor(getContext(), R.color.signal_text_secondary) - : ContextCompat.getColor(getContext(), R.color.signal_text_primary)); - if (thread.getDate() > 0) { CharSequence date = DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, thread.getDate()); dateView.setText(date); @@ -213,13 +213,13 @@ public final class ConversationListItem extends ConstraintLayout observeDisplayBody(null); setSubjectViewText(null); - this.selectedThreads = Collections.emptySet(); - this.glideRequests = glideRequests; + this.selectedThreads = Collections.emptySet(); + this.glideRequests = glideRequests; + this.locale = locale; + this.highlightSubstring = highlightSubstring; - - fromView.setText(contact); - fromView.setText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), new SpannableString(fromView.getText()), highlightSubstring)); - setSubjectViewText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), contact.getE164().or(""), highlightSubstring)); + fromView.setText(SearchUtil.getHighlightedSpan(locale, SpanUtil::getBoldSpan, new SpannableString(contact.getDisplayName(getContext())), highlightSubstring, SearchUtil.MATCH_ALL)); + setSubjectViewText(SearchUtil.getHighlightedSpan(locale, SpanUtil::getBoldSpan, contact.getE164().or(""), highlightSubstring, SearchUtil.MATCH_ALL)); dateView.setText(""); archivedView.setVisibility(GONE); unreadIndicator.setVisibility(GONE); @@ -241,11 +241,13 @@ public final class ConversationListItem extends ConstraintLayout observeDisplayBody(null); setSubjectViewText(null); - this.selectedThreads = Collections.emptySet(); - this.glideRequests = glideRequests; + this.selectedThreads = Collections.emptySet(); + this.glideRequests = glideRequests; + this.locale = locale; + this.highlightSubstring = highlightSubstring; fromView.setText(recipient.get(), true); - setSubjectViewText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), messageResult.getBodySnippet(), highlightSubstring)); + setSubjectViewText(SearchUtil.getHighlightedSpan(locale, SpanUtil::getBoldSpan, messageResult.getBodySnippet(), highlightSubstring, SearchUtil.MATCH_ALL)); dateView.setText(DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, messageResult.getReceivedTimestampMs())); archivedView.setVisibility(GONE); unreadIndicator.setVisibility(GONE); @@ -346,10 +348,10 @@ public final class ConversationListItem extends ConstraintLayout private void setThumbnailSnippet(ThreadRecord thread) { if (thread.getSnippetUri() != null) { - this.thumbnailView.setVisibility(View.VISIBLE); + this.thumbnailView.setVisibility(VISIBLE); this.thumbnailView.setImageResource(glideRequests, thread.getSnippetUri()); } else { - this.thumbnailView.setVisibility(View.GONE); + this.thumbnailView.setVisibility(GONE); } } @@ -401,11 +403,12 @@ public final class ConversationListItem extends ConstraintLayout } private void setUnreadIndicator(ThreadRecord thread) { - if ((thread.isOutgoing() && !thread.isForcedUnread()) || thread.isRead()) { + if ((thread.isOutgoing() && !thread.isForcedUnread()) || thread.isRead() || unreadCount == 0) { unreadIndicator.setVisibility(View.GONE); return; } + String count = unreadCount > 100 ? String.valueOf(unreadCount) : "+99"; unreadIndicator.setText(unreadCount > 0 ? String.valueOf(unreadCount) : " "); unreadIndicator.setVisibility(View.VISIBLE); } @@ -417,14 +420,18 @@ public final class ConversationListItem extends ConstraintLayout return; } - fromView.setText(recipient, unreadCount == 0); + if (highlightSubstring != null) { + String name = recipient.isSelf() ? getContext().getString(R.string.note_to_self) : recipient.getDisplayName(getContext()); + fromView.setText(SearchUtil.getHighlightedSpan(locale, SpanUtil::getBoldSpan, new SpannableString(name), highlightSubstring, SearchUtil.MATCH_ALL)); + } else { + fromView.setText(recipient, unreadCount == 0); + } contactPhotoImage.setAvatar(glideRequests, recipient, !batchMode); setRippleColor(recipient); } private static @NonNull LiveData getThreadDisplayBody(@NonNull Context context, @NonNull ThreadRecord thread) { - int defaultTint = thread.isRead() ? ContextCompat.getColor(context, R.color.signal_text_secondary) - : ContextCompat.getColor(context, R.color.signal_text_primary); + int defaultTint = ContextCompat.getColor(context, R.color.signal_text_secondary); if (!thread.isMessageRequestAccepted()) { return emphasisAdded(context, context.getString(R.string.ThreadRecord_message_request), defaultTint); @@ -520,8 +527,7 @@ public final class ConversationListItem extends ConstraintLayout : recipient.getShortDisplayName(context)) + ": "; SpannableString spannable = new SpannableString(sender + body); - spannable.setSpan(new TextAppearanceSpan(context, read ? R.style.Signal_Text_Preview_Medium_Secondary - : R.style.Signal_Text_Preview_Medium_Primary), + spannable.setSpan(SpanUtil.getBoldSpan(), 0, sender.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchAdapter.java index 8753b908fd..ef7c767730 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchAdapter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListSearchAdapter.java @@ -96,7 +96,7 @@ class ConversationListSearchAdapter extends RecyclerView.Adapter> ranges = getHighlightRanges(locale, text.toString(), highlight); SpannableString spanned = new SpannableString(text); + List> ranges; + + switch (matchMode) { + case STRICT: + ranges = getStrictHighlightRanges(locale, text.toString(), highlight); + break; + case MATCH_ALL: + ranges = getHighlightRanges(locale, text.toString(), highlight); + break; + default: + throw new InvalidParameterException("match mode must be STRICT or MATCH_ALL: " + matchMode); + } + if (matchMode == STRICT) { + ranges = getStrictHighlightRanges(locale, text.toString(), highlight); + } else { + ranges = getHighlightRanges(locale, text.toString(), highlight); + } for (Pair range : ranges) { spanned.setSpan(styleFactory.create(), range.first(), range.second(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); @@ -57,9 +79,9 @@ public class SearchUtil { return spanned; } - static List> getHighlightRanges(@NonNull Locale locale, - @NonNull String text, - @NonNull String highlight) + static List> getStrictHighlightRanges(@NonNull Locale locale, + @NonNull String text, + @NonNull String highlight) { if (text.length() == 0) { return Collections.emptyList(); @@ -97,6 +119,39 @@ public class SearchUtil { return ranges; } + static List> getHighlightRanges(@NonNull Locale locale, + @NonNull String text, + @NonNull String highlight) + { + if (text.length() == 0) { + return Collections.emptyList(); + } + + String normalizedText = text.toLowerCase(locale); + String normalizedHighlight = highlight.toLowerCase(locale); + List highlightTokens = Stream.of(normalizedHighlight.split("\\s")).filter(s -> s.trim().length() > 0).toList(); + + List> ranges = new LinkedList<>(); + + int lastHighlightEndIndex = 0; + + for (String highlightToken : highlightTokens) { + int index = 0; + lastHighlightEndIndex = 0; + + while (index != -1) { + index = normalizedText.indexOf(highlightToken, lastHighlightEndIndex); + if (index != -1) { + lastHighlightEndIndex = index + highlightToken.length(); + ranges.add(new Pair<>(index, lastHighlightEndIndex)); + index = lastHighlightEndIndex; + } + } + } + + return ranges; + } + public interface StyleFactory { CharacterStyle create(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java index f0e3904d3c..7f27d51173 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/SpanUtil.java @@ -13,12 +13,15 @@ import android.text.TextPaint; import android.text.TextUtils; import android.text.style.AbsoluteSizeSpan; import android.text.style.BulletSpan; +import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.DynamicDrawableSpan; import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; +import android.text.style.MetricAffectingSpan; import android.text.style.RelativeSizeSpan; import android.text.style.StyleSpan; +import android.text.style.TypefaceSpan; import android.view.View; import androidx.annotation.ColorInt; @@ -34,6 +37,9 @@ public final class SpanUtil { public static final String SPAN_PLACE_HOLDER = "<<>>"; + private final static Typeface BOLD_TYPEFACE = Typeface.create("sans-serif-medium", Typeface.NORMAL); + private final static Typeface LIGHT_TYPEFACE = Typeface.create("sans-serif", Typeface.NORMAL); + public static CharSequence italic(CharSequence sequence) { return italic(sequence, sequence.length()); } @@ -205,4 +211,20 @@ public final class SpanUtil { builder.replace(index, index + SpanUtil.SPAN_PLACE_HOLDER.length(), span); return builder; } + + public static CharacterStyle getBoldSpan() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + return new TypefaceSpan(BOLD_TYPEFACE); + } else { + return new StyleSpan(Typeface.BOLD); + } + } + + public static CharacterStyle getNormalSpan() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + return new TypefaceSpan(LIGHT_TYPEFACE); + } else { + return new StyleSpan(Typeface.NORMAL); + } + } } diff --git a/app/src/main/res/drawable-night/unread_count_background_new.xml b/app/src/main/res/drawable-night/unread_count_background_new.xml new file mode 100644 index 0000000000..01de9a90b3 --- /dev/null +++ b/app/src/main/res/drawable-night/unread_count_background_new.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/unread_count_background_new.xml b/app/src/main/res/drawable/unread_count_background_new.xml new file mode 100644 index 0000000000..4d8b1af10d --- /dev/null +++ b/app/src/main/res/drawable/unread_count_background_new.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/conversation_list_fragment.xml b/app/src/main/res/layout/conversation_list_fragment.xml index 6aa8aacc01..fd56992ae7 100644 --- a/app/src/main/res/layout/conversation_list_fragment.xml +++ b/app/src/main/res/layout/conversation_list_fragment.xml @@ -25,6 +25,7 @@ android:minHeight="?attr/actionBarSize" android:theme="?attr/actionBarStyle" android:visibility="gone" + app:contentInsetStart="0dp" app:layout_constraintTop_toTopOf="parent" tools:visibility="visible"> @@ -34,14 +35,11 @@ @@ -63,7 +61,7 @@ android:id="@+id/conversation_list_title" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="6dp" + android:layout_marginStart="26dp" android:text="@string/app_name" android:textAlignment="viewStart" android:textColor="@color/signal_text_primary" diff --git a/app/src/main/res/layout/conversation_list_item_header.xml b/app/src/main/res/layout/conversation_list_item_header.xml deleted file mode 100644 index da3ae9e1f5..0000000000 --- a/app/src/main/res/layout/conversation_list_item_header.xml +++ /dev/null @@ -1,12 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/conversation_list_item_view.xml b/app/src/main/res/layout/conversation_list_item_view.xml index e367dfbf3c..4b1a6bd88e 100644 --- a/app/src/main/res/layout/conversation_list_item_view.xml +++ b/app/src/main/res/layout/conversation_list_item_view.xml @@ -4,56 +4,58 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="72dp" + android:layout_height="86dp" android:background="@drawable/conversation_list_item_background" android:focusable="true" android:nextFocusLeft="@+id/container" android:nextFocusRight="@+id/fab" - android:paddingStart="16dp" - android:paddingEnd="16dp"> + android:paddingStart="@dimen/dsl_settings_gutter" + android:paddingEnd="@dimen/dsl_settings_gutter"> + android:layout_marginBottom="27dp" + app:layout_constraintEnd_toStartOf="@id/conversation_list_item_avatar_barrier" + app:layout_constraintBottom_toBottomOf="@id/conversation_list_item_avatar" + tools:text="9" /> @@ -65,24 +67,24 @@ android:paddingTop="2dp" android:visibility="gone" app:useSmallIcon="true" - app:layout_constraintTop_toTopOf="@id/conversation_list_item_summary" - app:layout_constraintBottom_toBottomOf="@id/conversation_list_item_summary" + app:layout_constraintTop_toBottomOf="@id/conversation_list_item_name" app:layout_constraintStart_toStartOf="@id/conversation_list_item_name" tools:visibility="visible" /> - + app:layout_constraintEnd_toStartOf="@id/conversation_list_item_summary_barrier"/> + tools:visibility="gone" + app:thumbnail_radius="8dp" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintEnd_toStartOf="@id/conversation_list_item_date"/> - + android:layout_marginStart="12dp" + android:layout_marginTop="6dp" + android:gravity="center" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/conversation_list_item_date"> - + + + + + + android:layout_height="match_parent" + app:barrierDirection="end" + app:constraint_referenced_ids="conversation_list_item_avatar" + app:barrierMargin="@dimen/unread_count_bubble_barrier_margin"/> - + app:barrierAllowsGoneWidgets="false" + app:constraint_referenced_ids="conversation_list_item_thumbnail,conversation_list_item_status_container" /> diff --git a/app/src/main/res/layout/dsl_section_header.xml b/app/src/main/res/layout/dsl_section_header.xml index 2a8bcb7449..3d465aa1c0 100644 --- a/app/src/main/res/layout/dsl_section_header.xml +++ b/app/src/main/res/layout/dsl_section_header.xml @@ -14,6 +14,5 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Signal.Body1.Bold" - android:textStyle="bold" tools:text="Section Header" /> diff --git a/app/src/main/res/layout/search_result_list_divider.xml b/app/src/main/res/layout/search_result_list_divider.xml deleted file mode 100644 index de377cd033..0000000000 --- a/app/src/main/res/layout/search_result_list_divider.xml +++ /dev/null @@ -1,14 +0,0 @@ - - diff --git a/app/src/main/res/layout/v2_media_review_fragment.xml b/app/src/main/res/layout/v2_media_review_fragment.xml index 700846ecc1..62eb363303 100644 --- a/app/src/main/res/layout/v2_media_review_fragment.xml +++ b/app/src/main/res/layout/v2_media_review_fragment.xml @@ -27,7 +27,7 @@ tools:alpha="1" tools:visibility="visible" /> - + + -4dp + \ No newline at end of file diff --git a/app/src/main/res/values-sw360dp/dimens.xml b/app/src/main/res/values-sw360dp/dimens.xml index c3dc4c6a24..146f23d275 100644 --- a/app/src/main/res/values-sw360dp/dimens.xml +++ b/app/src/main/res/values-sw360dp/dimens.xml @@ -29,4 +29,6 @@ 16dp 160dp + + 34dp \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 7d5387d585..b92df485fe 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -108,8 +108,9 @@ 16dp 10dp - 13sp - 26sp + 12.5dp + 25dp + 4dp 41dp 12dp @@ -200,4 +201,6 @@ 12dp 100dp + + 26dp diff --git a/app/src/test/java/org/thoughtcrime/securesms/util/SearchUtilTest.java b/app/src/test/java/org/thoughtcrime/securesms/util/SearchUtilTest.java index fcca0bad43..3dfdcb6555 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/util/SearchUtilTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/util/SearchUtilTest.java @@ -14,6 +14,64 @@ public class SearchUtilTest { private static final Locale LOCALE = Locale.ENGLISH; + @Test + public void getStrictHighlightRanges_singleHighlightToken() { + String text = "abc"; + String highlight = "a"; + List> result = SearchUtil.getStrictHighlightRanges(LOCALE, text, highlight); + + assertEquals(Arrays.asList(new Pair<>(0, 1)), result); + } + + @Test + public void getStrictHighlightRanges_singleHighlightTokenWithNewLines() { + String text = "123\n\n\nabc"; + String highlight = "a"; + List> result = SearchUtil.getStrictHighlightRanges(LOCALE, text, highlight); + + assertEquals(Arrays.asList(new Pair<>(6, 7)), result); + } + + @Test + public void getStrictHighlightRanges_multipleHighlightTokens() { + String text = "a bc"; + String highlight = "a b"; + List> result = SearchUtil.getStrictHighlightRanges(LOCALE, text, highlight); + + assertEquals(Arrays.asList(new Pair<>(0, 1), new Pair<>(2, 3)), result); + + + text = "abc def"; + highlight = "ab de"; + result = SearchUtil.getStrictHighlightRanges(LOCALE, text, highlight); + + assertEquals(Arrays.asList(new Pair<>(0, 2), new Pair<>(4, 6)), result); + } + + @Test + public void getStrictHighlightRanges_onlyHighlightPrefixes() { + String text = "abc"; + String highlight = "b"; + List> result = SearchUtil.getStrictHighlightRanges(LOCALE, text, highlight); + + assertTrue(result.isEmpty()); + + text = "abc"; + highlight = "c"; + result = SearchUtil.getStrictHighlightRanges(LOCALE, text, highlight); + + assertTrue(result.isEmpty()); + } + + @Test + public void getStrictHighlightRanges_resultNotInFirstToken() { + String text = "abc def ghi"; + String highlight = "gh"; + List> result = SearchUtil.getStrictHighlightRanges(LOCALE, text, highlight); + + assertEquals(Arrays.asList(new Pair<>(8, 10)), result); + } + @Test public void getHighlightRanges_singleHighlightToken() { String text = "abc"; @@ -24,51 +82,20 @@ public class SearchUtilTest { } @Test - public void getHighlightRanges_singleHighlightTokenWithNewLines() { - String text = "123\n\n\nabc"; + public void getHighlightRanges_singleHighlightTokenMultipleMatches() { + String text = "blabla"; String highlight = "a"; List> result = SearchUtil.getHighlightRanges(LOCALE, text, highlight); - assertEquals(Arrays.asList(new Pair<>(6, 7)), result); + assertEquals(Arrays.asList(new Pair<>(2, 3), new Pair<>(5, 6)), result); } @Test - public void getHighlightRanges_multipleHighlightTokens() { - String text = "a bc"; - String highlight = "a b"; + public void getHighlightRanges_multipleHighlightTokenMultipleMatches() { + String text = "test search test string"; + String highlight = "test str"; List> result = SearchUtil.getHighlightRanges(LOCALE, text, highlight); - assertEquals(Arrays.asList(new Pair<>(0, 1), new Pair<>(2, 3)), result); - - - text = "abc def"; - highlight = "ab de"; - result = SearchUtil.getHighlightRanges(LOCALE, text, highlight); - - assertEquals(Arrays.asList(new Pair<>(0, 2), new Pair<>(4, 6)), result); - } - - @Test - public void getHighlightRanges_onlyHighlightPrefixes() { - String text = "abc"; - String highlight = "b"; - List> result = SearchUtil.getHighlightRanges(LOCALE, text, highlight); - - assertTrue(result.isEmpty()); - - text = "abc"; - highlight = "c"; - result = SearchUtil.getHighlightRanges(LOCALE, text, highlight); - - assertTrue(result.isEmpty()); - } - - @Test - public void getHighlightRanges_resultNotInFirstToken() { - String text = "abc def ghi"; - String highlight = "gh"; - List> result = SearchUtil.getHighlightRanges(LOCALE, text, highlight); - - assertEquals(Arrays.asList(new Pair<>(8, 10)), result); + assertEquals(Arrays.asList(new Pair<>(0, 4), new Pair<>(12, 16), new Pair<>(17,20)), result); } }