diff --git a/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java b/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java index 66735c8a5e1..e3ece219abf 100644 --- a/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java +++ b/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java @@ -33,9 +33,11 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; import com.android.settings.datetime.timezone.BaseTimeZonePicker.OnListItemClickListener; +import java.text.Normalizer; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.regex.Pattern; /** * Used with {@class BaseTimeZonePicker}. It renders text in each item into list view. A list of @@ -48,6 +50,9 @@ public class BaseTimeZoneAdapter @VisibleForTesting static final int TYPE_ITEM = 1; + private static final Pattern PATTERN_REMOVE_DIACRITICS = Pattern.compile( + "\\p{InCombiningDiacriticalMarks}+"); + private final List mOriginalItems; private final OnListItemClickListener mOnListItemClickListener; private final Locale mLocale; @@ -183,6 +188,19 @@ public class BaseTimeZoneAdapter } } + /** + * Removes diacritics (e.g. accents) from a string + */ + private static String removeDiacritics(final String str) { + if (str == null || str.isEmpty()) { + return str; + } + // decomposes the original characters into a base character and a diacritic sign + final String decomposed = Normalizer.normalize(str, Normalizer.Form.NFKD); + // replaces the diacritic signs with empty strings + return PATTERN_REMOVE_DIACRITICS.matcher(decomposed).replaceAll(""); + } + @VisibleForTesting public static class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { @@ -241,13 +259,14 @@ public class BaseTimeZoneAdapter if (TextUtils.isEmpty(prefix)) { newItems = mOriginalItems; } else { - final String prefixString = prefix.toString().toLowerCase(mLocale); + final String prefixString = removeDiacritics( + prefix.toString().toLowerCase(mLocale)); newItems = new ArrayList<>(); for (T item : mOriginalItems) { outer: for (String searchKey : item.getSearchKeys()) { - searchKey = searchKey.toLowerCase(mLocale); + searchKey = removeDiacritics(searchKey.toLowerCase(mLocale)); // First match against the whole, non-splitted value if (searchKey.startsWith(prefixString)) { newItems.add(item); diff --git a/src/com/android/settings/datetime/timezone/RegionZonePicker.java b/src/com/android/settings/datetime/timezone/RegionZonePicker.java index 1bc68a10d4c..06c0db59ac4 100644 --- a/src/com/android/settings/datetime/timezone/RegionZonePicker.java +++ b/src/com/android/settings/datetime/timezone/RegionZonePicker.java @@ -111,7 +111,7 @@ public class RegionZonePicker extends BaseTimeZoneInfoPicker { /** * Returns a list of {@link TimeZoneInfo} objects. The returned list will be sorted properly for - * display in the locale.It may be smaller than the input collection, if equivalent IDs are + * display in the locale. It may be smaller than the input collection, if equivalent IDs are * passed in. * * @param timeZoneIds a list of Olson IDs. diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapterTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapterTest.java index 4f23b60c38d..77fafdecec6 100644 --- a/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapterTest.java +++ b/tests/robotests/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapterTest.java @@ -22,39 +22,43 @@ import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.robolectric.RobolectricTestRunner; @RunWith(RobolectricTestRunner.class) public class BaseTimeZoneAdapterTest { @Test public void testFilter() throws InterruptedException { - TestItem US = new TestItem("United States"); - TestItem HK = new TestItem("Hong Kong"); - TestItem UK = new TestItem("United Kingdom", new String[] { "United Kingdom", + TestItem unitedStates = new TestItem("United States"); + TestItem hongKong = new TestItem("Hong Kong"); + TestItem unitedKingdom = new TestItem("United Kingdom", new String[]{"United Kingdom", "Great Britain"}); - TestItem secretCountry = new TestItem("no name", new String[] { "Secret"}); + TestItem reunion = new TestItem("Réunion"); + TestItem secretCountry = new TestItem("no name", new String[]{"Secret"}); List items = new ArrayList<>(); - items.add(US); - items.add(HK); - items.add(UK); + items.add(unitedStates); + items.add(hongKong); + items.add(unitedKingdom); + items.add(reunion); items.add(secretCountry); TestTimeZoneAdapter adapter = new TestTimeZoneAdapter(items); assertSearch(adapter, "", items.toArray(new TestItem[0])); - assertSearch(adapter, "Unit", US, UK); - assertSearch(adapter, "kon", HK); - assertSearch(adapter, "brit", UK); + assertSearch(adapter, "Unit", unitedStates, unitedKingdom); + assertSearch(adapter, "kon", hongKong); + assertSearch(adapter, "brit", unitedKingdom); assertSearch(adapter, "sec", secretCountry); + assertSearch(adapter, "reun", reunion); // no accent in search, accent in result + assertSearch(adapter, "Réunion", reunion); // accents in search and result } - private void assertSearch(TestTimeZoneAdapter adapter , String searchText, TestItem... items) + private void assertSearch(TestTimeZoneAdapter adapter, String searchText, TestItem... items) throws InterruptedException { Observer observer = new Observer(adapter); adapter.getFilter().filter(searchText); @@ -89,7 +93,10 @@ public class BaseTimeZoneAdapterTest { private static class TestTimeZoneAdapter extends BaseTimeZoneAdapter { private TestTimeZoneAdapter(List items) { - super(items, position -> {}, Locale.US, false /* showItemSummary */, + super(items, + position -> {}, + Locale.US, + false /* showItemSummary */, null /* headerText */); } } @@ -100,7 +107,7 @@ public class BaseTimeZoneAdapterTest { private final String[] mSearchKeys; TestItem(String title) { - this(title, new String[] { title }); + this(title, new String[]{title}); } TestItem(String title, String[] searchKeys) {