Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit be0a3635 authored by Danny Baumann's avatar Danny Baumann Committed by Gerrit Code Review
Browse files

Improve T9 name normalization code

- Properly highlight nickname matches
- Make sorting more intuitive
- Highlight whole matched entry for pinyin matches instead of nothing
- Cleanup

This fixes issue CYAN-201.

Change-Id: I3346dd5bd117278718a5f1048ec96a743b7436b1
parent 7f44b0ee
Loading
Loading
Loading
Loading
+55 −41
Original line number Diff line number Diff line
@@ -126,8 +126,7 @@ public class T9SearchCache implements ComponentCallbacks2 {
    private ArrayList<ContactItem> mContacts = new ArrayList<ContactItem>();
    private String mPrevInput;

    private String mT9Chars;
    private String mT9Digits;
    private NameToNumber mNormalizer;

    private BroadcastReceiver mLocaleChangedReceiver = new BroadcastReceiver() {
        @Override
@@ -136,11 +135,11 @@ public class T9SearchCache implements ComponentCallbacks2 {
                return;
            }

            NameToNumber normalizer = NameToNumberFactory.create(mContext, mT9Chars, mT9Digits);
            initNormalizer();
            for (ContactItem contact : mContacts) {
                for (NameMatchEntry entry : contact.nameEntries.values()) {
                    if (entry.value != null) {
                        entry.normalValue = normalizer.convert(entry.value);
                        entry.normalValue = mNormalizer.convert(entry.value);
                    }
                }
            }
@@ -220,9 +219,7 @@ public class T9SearchCache implements ComponentCallbacks2 {

        @Override
        protected Void doInBackground(Void... args) {
            initT9Map();

            NameToNumber normalizer = NameToNumberFactory.create(mContext, mT9Chars, mT9Digits);
            initNormalizer();

            Cursor contact = mContext.getContentResolver().query(
                    Contacts.CONTENT_URI, CONTACT_PROJECTION, CONTACT_QUERY,
@@ -273,9 +270,9 @@ public class T9SearchCache implements ComponentCallbacks2 {
                }

                for (ContactItem item : contactItems) {
                    item.addNameEntry(ENTRY_NAME, contact.getString(CONTACT_COLUMN_NAME), normalizer);
                    item.addNameEntry(ENTRY_NICKNAME, nickName, normalizer);
                    item.addNameEntry(ENTRY_ORGANIZATION, organization, normalizer);
                    item.addNameEntry(ENTRY_NAME, contact.getString(CONTACT_COLUMN_NAME), mNormalizer);
                    item.addNameEntry(ENTRY_NICKNAME, nickName, mNormalizer);
                    item.addNameEntry(ENTRY_ORGANIZATION, organization, mNormalizer);
                    contacts.add(item);
                }
            }
@@ -417,11 +414,7 @@ public class T9SearchCache implements ComponentCallbacks2 {
            for (NameMatchEntry entry : item.nameEntries.values()) {
                pos = entry.normalValue != null ? entry.normalValue.indexOf(number) : -1;
                if (pos != -1) {
                    int lastSpace = entry.normalValue.lastIndexOf("0", pos);
                    if (lastSpace == -1) {
                        lastSpace = 0;
                    }
                    entry.matchId = pos - lastSpace;
                    entry.matchId = pos;
                    hasNameMatch = true;
                } else {
                    entry.matchId = -1;
@@ -465,45 +458,57 @@ public class T9SearchCache implements ComponentCallbacks2 {
    private static final Comparator<ContactItem> sNameComparator = new Comparator<ContactItem>() {
        @Override
        public int compare(ContactItem lhs, ContactItem rhs) {
            int ret;
            // sort by contact frequency first - higher contact frequency first
            if (lhs.timesContacted != rhs.timesContacted) {
                return -Integer.compare(lhs.timesContacted, rhs.timesContacted);
            }

            // then by primary state - primary first
            if (lhs.isSuperPrimary != rhs.isSuperPrimary) {
                return lhs.isSuperPrimary ? -1 : 1;
            }

            // and finally by match position in the entries - leftmost match first
            int lowestMatchLeft = Integer.MAX_VALUE, lowestMatchRight = Integer.MAX_VALUE;
            for (int i = 0; i < MATCH_ENTRY_COUNT; i++) {
                ret = Integer.compare(lhs.nameEntries.get(i).matchId, rhs.nameEntries.get(i).matchId);
                if (ret != 0) {
                    return ret;
                NameMatchEntry l = lhs.nameEntries.get(i);
                NameMatchEntry r = rhs.nameEntries.get(i);
                if (l.matchId >= 0 && l.matchId < lowestMatchLeft) {
                    lowestMatchLeft = l.matchId;
                }
                if (r.matchId >= 0 && r.matchId < lowestMatchRight) {
                    lowestMatchRight = r.matchId;
                }
            ret = Integer.compare(rhs.timesContacted, lhs.timesContacted);
            if (ret != 0) {
                return ret;
            }

            return Boolean.compare(rhs.isSuperPrimary, lhs.isSuperPrimary);
            return Integer.compare(lowestMatchLeft, lowestMatchRight);
        }
    };

    private static final Comparator<ContactItem> sNumberComparator = new Comparator<ContactItem>() {
        @Override
        public int compare(ContactItem lhs, ContactItem rhs) {
            int ret = Integer.compare(lhs.numberMatchId, rhs.numberMatchId);
            if (ret == 0) ret = Integer.compare(rhs.timesContacted, lhs.timesContacted);
            // as above: contact frequency first, then primary state, then position
            int ret = -Integer.compare(rhs.timesContacted, lhs.timesContacted);
            if (ret == 0) ret = Boolean.compare(rhs.isSuperPrimary, lhs.isSuperPrimary);
            if (ret == 0) ret = Integer.compare(lhs.numberMatchId, rhs.numberMatchId);
            return ret;
        }
    };

    private void initT9Map() {
        StringBuilder bT9Chars = new StringBuilder();
        StringBuilder bT9Digits = new StringBuilder();
    private void initNormalizer() {
        StringBuilder t9Chars = new StringBuilder();
        StringBuilder t9Digits = new StringBuilder();

        for (String item : mContext.getResources().getStringArray(R.array.t9_map)) {
            bT9Chars.append(item);
            t9Chars.append(item);
            for (int i = 0; i < item.length(); i++) {
                bT9Digits.append(item.charAt(0));
                t9Digits.append(item.charAt(0));
            }
        }

        mT9Chars = bT9Chars.toString();
        mT9Digits = bT9Digits.toString();
        mNormalizer = NameToNumberFactory.create(mContext,
                t9Chars.toString(), t9Digits.toString());
    }

    private String removeNonDigits(String number) {
@@ -575,21 +580,30 @@ public class T9SearchCache implements ComponentCallbacks2 {
                        nameBuilder.append(entry.prefix);
                    }

                    int start = nameBuilder.length() + entry.matchId;
                    int firstPos = nameBuilder.length();
                    nameBuilder.append(entry.value);

                    if (!TextUtils.isEmpty(entry.postfix)) {
                        nameBuilder.append(entry.postfix);
                    }

                    if (entry.matchId != -1) {
                        if (start <= entry.value.length()
                                && start + mPrevInput.length() <= entry.value.length()) {
                            nameBuilder.setSpan(new ForegroundColorSpan(mHighlightColor),
                                    start, start + mPrevInput.length(),
                                    Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                    if (entry.matchId < 0) {
                        continue;
                    }

                    int start, end;

                    if (entry.matchId > entry.value.length()
                            || entry.matchId + mPrevInput.length() > entry.value.length()) {
                        start = firstPos;
                        end = firstPos + entry.value.length();
                    } else {
                        start = firstPos + entry.matchId;
                        end = start + mPrevInput.length();
                    }

                    nameBuilder.setSpan(new ForegroundColorSpan(mHighlightColor),
                            start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                }

                SpannableStringBuilder numberBuilder = new SpannableStringBuilder();
+15 −36
Original line number Diff line number Diff line

package com.android.contacts.dialpad.util;

import android.text.TextUtils;

import com.android.contacts.util.HanziToPinyin;

/**
 * @author Barami Implementation for Korean normalization. This will change
 *         Hangul character to number by Choseong(Korean word of initial
 *         character).
 */
public class NameToNumberChinese extends NameToNumber {
    public NameToNumberChinese(String t9Chars, String t9Digits) {
        super(t9Chars, t9Digits);
        // TODO Auto-generated constructor stub
    }

    private String convertToT9(String hzPinYin) {
        StringBuilder sb = new StringBuilder(hzPinYin.length());
        int iTotal = hzPinYin.length();
        for (int i = 0; i < iTotal; i++) {
            int pos = t9Chars.indexOf(hzPinYin.charAt(i));
            if (-1 == pos) {
                pos = 0;
            }
            sb.append(t9Digits.charAt(pos));
        }

        return sb.toString();
    }

    @Override
    public String convert(String name) {
        String t9 = null;
        final HanziToPinyin pinyin = HanziToPinyin.getInstance();
        String hzPinYin = pinyin.getFirstPinYin(name).toLowerCase();

        if (TextUtils.isEmpty(hzPinYin)) {
            return super.convert(name);
        }

        String hzPinYin = HanziToPinyin.getInstance().getFirstPinYin(name).toLowerCase();
        String result = super.convert(hzPinYin);

        if (hzPinYin != null && !hzPinYin.isEmpty()) {
            t9 = convertToT9(hzPinYin);
        //Append the full ping yin at the end of the first ping yin
            hzPinYin = HanziToPinyin.getInstance().getFullPinYin(name).toLowerCase();
            if (hzPinYin != null && !hzPinYin.isEmpty()) {
                t9 += " " + convertToT9(hzPinYin);
        hzPinYin = pinyin.getFullPinYin(name).toLowerCase();
        if (!TextUtils.isEmpty(hzPinYin)) {
            result += " " + super.convert(hzPinYin);
        }
        } else {
            // Add English name search support
            t9 = convertToT9(name.toLowerCase());
        }

        return t9;

        return result;
    }
}
+0 −1
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ public class NameToNumberKorean extends NameToNumber {

    public NameToNumberKorean(String t9Chars, String t9Digits) {
        super(t9Chars, t9Digits);
        // TODO Auto-generated constructor stub
    }

    @Override