From 7397deac578e075c2bc27ada0ff79dc666099649 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Thu, 30 Nov 2023 12:46:26 +0100 Subject: [PATCH] add cache for next word suggestions --- .../openboard/inputmethod/latin/LatinIME.java | 1 + .../openboard/inputmethod/latin/Suggest.java | 56 ++++++++++++++----- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/LatinIME.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/LatinIME.java index 788c786b2..6aface9dc 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/LatinIME.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/LatinIME.java @@ -660,6 +660,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen resetDictionaryFacilitatorIfNecessary(); } refreshPersonalizationDictionarySession(currentSettingsValues); + Suggest.nextWordSuggestionsCache.clear(); mStatsUtilsManager.onLoadSettings(this /* context */, currentSettingsValues); } diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/Suggest.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/Suggest.java index 6fd809edf..c13c6678b 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/Suggest.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/Suggest.java @@ -33,6 +33,8 @@ import static org.dslul.openboard.inputmethod.latin.define.DecoderSpecificConsta import androidx.annotation.NonNull; +import kotlin.collections.CollectionsKt; + /** * This class loads a dictionary and provides a list of suggestions for a given sequence of * characters. This includes corrections and completions. @@ -61,6 +63,9 @@ public final class Suggest { MAXIMUM_AUTO_CORRECT_LENGTH_FOR_GERMAN); } + // cleared whenever LatinIME.loadSettings is called, notably on changing layout and switching input fields + public static final HashMap nextWordSuggestionsCache = new HashMap<>(); + private float mAutoCorrectionThreshold; private float mPlausibilityThreshold; @@ -144,9 +149,11 @@ public final class Suggest { final int trailingSingleQuotesCount = StringUtils.getTrailingSingleQuotesCount(typedWordString); - final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults( - wordComposer.getComposedDataSnapshot(), ngramContext, keyboard, - settingsValuesForSuggestion, SESSION_ID_TYPING, inputStyleIfNotPrediction); + final SuggestionResults suggestionResults = typedWordString.isEmpty() + ? getNextWordSuggestions(ngramContext, keyboard, inputStyleIfNotPrediction, settingsValuesForSuggestion) + : mDictionaryFacilitator.getSuggestionResults( + wordComposer.getComposedDataSnapshot(), ngramContext, keyboard, + settingsValuesForSuggestion, SESSION_ID_TYPING, inputStyleIfNotPrediction); final Locale locale = mDictionaryFacilitator.getLocale(); final ArrayList suggestionsContainer = getTransformedSuggestedWordInfoList(wordComposer, suggestionResults, @@ -249,6 +256,8 @@ public final class Suggest { } // annoyingly complicated thing to avoid getting emptyWordSuggestions more than once + // todo: now with the cache just remove it... + // and best convert the class to kotlin, that should make it much more readable /** puts word infos for suggestions with an empty word in [infos], based on previously typed words */ private ArrayList putEmptyWordSuggestions(ArrayList infos, NgramContext ngramContext, Keyboard keyboard, SettingsValuesForSuggestion settingsValuesForSuggestion, @@ -256,17 +265,13 @@ public final class Suggest { if (infos.size() != 0) return infos; infos.add(null); infos.add(null); - final SuggestionResults emptyWordSuggestions = mDictionaryFacilitator.getSuggestionResults( - new ComposedData(new InputPointers(1), false, ""), ngramContext, - keyboard, settingsValuesForSuggestion, SESSION_ID_TYPING, inputStyleIfNotPrediction); - for (SuggestedWordInfo info : emptyWordSuggestions) { - if (infos.get(1) == null && typedWordString.equals(info.getWord())) { - infos.set(1, info); - } else if (infos.get(0) == null && firstSuggestionInContainer.equals(info.getWord())) { - infos.set(0, info); - } else if (infos.get(1) != null && infos.get(0) != null) - break; - } + final SuggestionResults emptyWordSuggestions = getNextWordSuggestions(ngramContext, keyboard, inputStyleIfNotPrediction, settingsValuesForSuggestion); + final SuggestedWordInfo nextWordSuggestionInfoForFirstSuggestionInContainer = + CollectionsKt.firstOrNull(emptyWordSuggestions, (word) -> word.mWord.equals(firstSuggestionInContainer)); + final SuggestedWordInfo nextWordSuggestionInfoForTypedWord = + CollectionsKt.firstOrNull(emptyWordSuggestions, (word) -> word.mWord.equals(typedWordString)); + infos.add(nextWordSuggestionInfoForFirstSuggestionInContainer); + infos.add(nextWordSuggestionInfoForTypedWord); return infos; } @@ -560,4 +565,25 @@ public final class Suggest { wordInfo.mSourceDict, wordInfo.mIndexOfTouchPointOfSecondWord, wordInfo.mAutoCommitFirstWordConfidence); } -} \ No newline at end of file + + /** get suggestions based on the current ngram context, with an empty typed word (that's what next word suggestions do) */ + // todo: integrate it into shouldBeAutoCorrected, remove putEmptySuggestions + // and make that thing more readable + private SuggestionResults getNextWordSuggestions(final NgramContext ngramContext, + final Keyboard keyboard, final int inputStyle, final SettingsValuesForSuggestion settingsValuesForSuggestion + ) { + final SuggestionResults cachedResults = nextWordSuggestionsCache.get(ngramContext); + if (cachedResults != null) + return cachedResults; + final SuggestionResults newResults = mDictionaryFacilitator.getSuggestionResults( + new ComposedData(new InputPointers(1), false, ""), + ngramContext, + keyboard, + settingsValuesForSuggestion, + SESSION_ID_TYPING, + inputStyle + ); + nextWordSuggestionsCache.put(ngramContext, newResults); + return newResults; + } +}