Merge "Improve multi-word suggestion handling for user history."
This commit is contained in:
commit
84070cbc74
3 changed files with 29 additions and 14 deletions
|
@ -169,6 +169,8 @@ public final class Constants {
|
||||||
// How many continuous deletes at which to start deleting at a higher speed.
|
// How many continuous deletes at which to start deleting at a higher speed.
|
||||||
public static final int DELETE_ACCELERATE_AT = 20;
|
public static final int DELETE_ACCELERATE_AT = 20;
|
||||||
|
|
||||||
|
public static final String WORD_SEPARATOR = " ";
|
||||||
|
|
||||||
public static boolean isValidCoordinate(final int coordinate) {
|
public static boolean isValidCoordinate(final int coordinate) {
|
||||||
// Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE},
|
// Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE},
|
||||||
// and {@link SPELL_CHECKER_COORDINATE}.
|
// and {@link SPELL_CHECKER_COORDINATE}.
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class DictionaryFacilitatorForSuggest {
|
||||||
private boolean mIsUserDictEnabled = false;
|
private boolean mIsUserDictEnabled = false;
|
||||||
private volatile CountDownLatch mLatchForWaitingLoadingMainDictionary = new CountDownLatch(0);
|
private volatile CountDownLatch mLatchForWaitingLoadingMainDictionary = new CountDownLatch(0);
|
||||||
// To synchronize assigning mDictionaries to ensure closing dictionaries.
|
// To synchronize assigning mDictionaries to ensure closing dictionaries.
|
||||||
private Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
|
|
||||||
private static final String[] DICT_TYPES_ORDERED_TO_GET_SUGGESTION =
|
private static final String[] DICT_TYPES_ORDERED_TO_GET_SUGGESTION =
|
||||||
new String[] {
|
new String[] {
|
||||||
|
@ -372,30 +372,42 @@ public class DictionaryFacilitatorForSuggest {
|
||||||
public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
|
public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
|
||||||
final String previousWord, final int timeStampInSeconds) {
|
final String previousWord, final int timeStampInSeconds) {
|
||||||
final Dictionaries dictionaries = mDictionaries;
|
final Dictionaries dictionaries = mDictionaries;
|
||||||
|
final String[] words = suggestion.split(Constants.WORD_SEPARATOR);
|
||||||
|
for (int i = 0; i < words.length; i++) {
|
||||||
|
final String currentWord = words[i];
|
||||||
|
final String prevWord = (i == 0) ? previousWord : words[i - 1];
|
||||||
|
final boolean wasCurrentWordAutoCapitalized = (i == 0) ? wasAutoCapitalized : false;
|
||||||
|
addWordToUserHistory(dictionaries, prevWord, currentWord,
|
||||||
|
wasCurrentWordAutoCapitalized, timeStampInSeconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addWordToUserHistory(final Dictionaries dictionaries, final String prevWord,
|
||||||
|
final String word, final boolean wasAutoCapitalized, final int timeStampInSeconds) {
|
||||||
final ExpandableBinaryDictionary userHistoryDictionary =
|
final ExpandableBinaryDictionary userHistoryDictionary =
|
||||||
dictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
|
dictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
|
||||||
if (userHistoryDictionary == null) {
|
if (userHistoryDictionary == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final int maxFreq = getMaxFrequency(suggestion);
|
final int maxFreq = getMaxFrequency(word);
|
||||||
if (maxFreq == 0) {
|
if (maxFreq == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final String suggestionLowerCase = suggestion.toLowerCase(dictionaries.mLocale);
|
final String lowerCasedWord = word.toLowerCase(dictionaries.mLocale);
|
||||||
final String secondWord;
|
final String secondWord;
|
||||||
if (wasAutoCapitalized) {
|
if (wasAutoCapitalized) {
|
||||||
if (isValidWord(suggestion, false /* ignoreCase */)
|
if (isValidWord(word, false /* ignoreCase */)
|
||||||
&& !isValidWord(suggestionLowerCase, false /* ignoreCase */)) {
|
&& !isValidWord(lowerCasedWord, false /* ignoreCase */)) {
|
||||||
// If the word was auto-capitalized and exists only as a capitalized word in the
|
// If the word was auto-capitalized and exists only as a capitalized word in the
|
||||||
// dictionary, then we must not downcase it before registering it. For example,
|
// dictionary, then we must not downcase it before registering it. For example,
|
||||||
// the name of the contacts in start-of-sentence position would come here with the
|
// the name of the contacts in start-of-sentence position would come here with the
|
||||||
// wasAutoCapitalized flag: if we downcase it, we'd register a lower-case version
|
// wasAutoCapitalized flag: if we downcase it, we'd register a lower-case version
|
||||||
// of that contact's name which would end up popping in suggestions.
|
// of that contact's name which would end up popping in suggestions.
|
||||||
secondWord = suggestion;
|
secondWord = word;
|
||||||
} else {
|
} else {
|
||||||
// If however the word is not in the dictionary, or exists as a lower-case word
|
// If however the word is not in the dictionary, or exists as a lower-case word
|
||||||
// only, then we consider that was a lower-case word that had been auto-capitalized.
|
// only, then we consider that was a lower-case word that had been auto-capitalized.
|
||||||
secondWord = suggestionLowerCase;
|
secondWord = lowerCasedWord;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// HACK: We'd like to avoid adding the capitalized form of common words to the User
|
// HACK: We'd like to avoid adding the capitalized form of common words to the User
|
||||||
|
@ -403,20 +415,20 @@ public class DictionaryFacilitatorForSuggest {
|
||||||
// consolidation is done.
|
// consolidation is done.
|
||||||
// TODO: Remove this hack when ready.
|
// TODO: Remove this hack when ready.
|
||||||
final int lowerCaseFreqInMainDict = dictionaries.hasDict(Dictionary.TYPE_MAIN) ?
|
final int lowerCaseFreqInMainDict = dictionaries.hasDict(Dictionary.TYPE_MAIN) ?
|
||||||
dictionaries.getDict(Dictionary.TYPE_MAIN).getFrequency(suggestionLowerCase) :
|
dictionaries.getDict(Dictionary.TYPE_MAIN).getFrequency(lowerCasedWord) :
|
||||||
Dictionary.NOT_A_PROBABILITY;
|
Dictionary.NOT_A_PROBABILITY;
|
||||||
if (maxFreq < lowerCaseFreqInMainDict
|
if (maxFreq < lowerCaseFreqInMainDict
|
||||||
&& lowerCaseFreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) {
|
&& lowerCaseFreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) {
|
||||||
// Use lower cased word as the word can be a distracter of the popular word.
|
// Use lower cased word as the word can be a distracter of the popular word.
|
||||||
secondWord = suggestionLowerCase;
|
secondWord = lowerCasedWord;
|
||||||
} else {
|
} else {
|
||||||
secondWord = suggestion;
|
secondWord = word;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
|
// We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
|
||||||
// We don't add words with 0-frequency (assuming they would be profanity etc.).
|
// We don't add words with 0-frequency (assuming they would be profanity etc.).
|
||||||
final boolean isValid = maxFreq > 0;
|
final boolean isValid = maxFreq > 0;
|
||||||
UserHistoryDictionary.addToDictionary(userHistoryDictionary, previousWord, secondWord,
|
UserHistoryDictionary.addToDictionary(userHistoryDictionary, prevWord, secondWord,
|
||||||
isValid, timeStampInSeconds);
|
isValid, timeStampInSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -604,7 +604,7 @@ public final class InputLogic {
|
||||||
if (null != candidate
|
if (null != candidate
|
||||||
&& mSuggestedWords.mSequenceNumber >= mAutoCommitSequenceNumber) {
|
&& mSuggestedWords.mSequenceNumber >= mAutoCommitSequenceNumber) {
|
||||||
if (candidate.mSourceDict.shouldAutoCommit(candidate)) {
|
if (candidate.mSourceDict.shouldAutoCommit(candidate)) {
|
||||||
final String[] commitParts = candidate.mWord.split(" ", 2);
|
final String[] commitParts = candidate.mWord.split(Constants.WORD_SEPARATOR, 2);
|
||||||
batchPointers.shift(candidate.mIndexOfTouchPointOfSecondWord);
|
batchPointers.shift(candidate.mIndexOfTouchPointOfSecondWord);
|
||||||
promotePhantomSpace(settingsValues);
|
promotePhantomSpace(settingsValues);
|
||||||
mConnection.commitText(commitParts[0], 0);
|
mConnection.commitText(commitParts[0], 0);
|
||||||
|
@ -1962,10 +1962,11 @@ public final class InputLogic {
|
||||||
final CharSequence chosenWordWithSuggestions =
|
final CharSequence chosenWordWithSuggestions =
|
||||||
SuggestionSpanUtils.getTextWithSuggestionSpan(mLatinIME, chosenWord,
|
SuggestionSpanUtils.getTextWithSuggestionSpan(mLatinIME, chosenWord,
|
||||||
suggestedWords);
|
suggestedWords);
|
||||||
mConnection.commitText(chosenWordWithSuggestions, 1);
|
// Use the 2nd previous word as the previous word because the 1st previous word is the word
|
||||||
// TODO: we pass 2 here, but would it be better to move this above and pass 1 instead?
|
// to be committed.
|
||||||
final String prevWord = mConnection.getNthPreviousWord(
|
final String prevWord = mConnection.getNthPreviousWord(
|
||||||
settingsValues.mSpacingAndPunctuations, 2);
|
settingsValues.mSpacingAndPunctuations, 2);
|
||||||
|
mConnection.commitText(chosenWordWithSuggestions, 1);
|
||||||
// Add the word to the user history dictionary
|
// Add the word to the user history dictionary
|
||||||
performAdditionToUserHistoryDictionary(settingsValues, chosenWord, prevWord);
|
performAdditionToUserHistoryDictionary(settingsValues, chosenWord, prevWord);
|
||||||
// TODO: figure out here if this is an auto-correct or if the best word is actually
|
// TODO: figure out here if this is an auto-correct or if the best word is actually
|
||||||
|
|
Loading…
Reference in a new issue