Update conversations list UI.

This commit is contained in:
Lucio Maciel
2021-09-03 17:38:20 -03:00
committed by Cody Henthorne
parent c84de8fa60
commit e09d162c1e
20 changed files with 330 additions and 211 deletions

View File

@@ -12,6 +12,7 @@ import com.annimon.stream.Stream;
import org.whispersystems.libsignal.util.Pair;
import java.security.InvalidParameterException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -19,10 +20,14 @@ import java.util.Locale;
public class SearchUtil {
public static final int STRICT = 0;
public static final int MATCH_ALL = 1;
public static Spannable getHighlightedSpan(@NonNull Locale locale,
@NonNull StyleFactory styleFactory,
@Nullable String text,
@Nullable String highlight)
@Nullable String highlight,
int matchMode)
{
if (TextUtils.isEmpty(text)) {
return new SpannableString("");
@@ -30,13 +35,14 @@ public class SearchUtil {
text = text.replaceAll("\n", " ");
return getHighlightedSpan(locale, styleFactory, new SpannableString(text), highlight);
return getHighlightedSpan(locale, styleFactory, new SpannableString(text), highlight, matchMode);
}
public static Spannable getHighlightedSpan(@NonNull Locale locale,
@NonNull StyleFactory styleFactory,
@Nullable Spannable text,
@Nullable String highlight)
@Nullable String highlight,
int matchMode)
{
if (TextUtils.isEmpty(text)) {
return new SpannableString("");
@@ -47,8 +53,24 @@ public class SearchUtil {
return text;
}
List<Pair<Integer, Integer>> ranges = getHighlightRanges(locale, text.toString(), highlight);
SpannableString spanned = new SpannableString(text);
List<Pair<Integer, Integer>> 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<Integer, Integer> 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<Pair<Integer, Integer>> getHighlightRanges(@NonNull Locale locale,
@NonNull String text,
@NonNull String highlight)
static List<Pair<Integer, Integer>> 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<Pair<Integer, Integer>> 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<String> highlightTokens = Stream.of(normalizedHighlight.split("\\s")).filter(s -> s.trim().length() > 0).toList();
List<Pair<Integer, Integer>> 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();
}

View File

@@ -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 = "<<<SPAN>>>";
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);
}
}
}