From a88250d634f631d699c536d2893fcfa1a5af46df Mon Sep 17 00:00:00 2001 From: Dimo Karaivanov Date: Wed, 8 Feb 2023 14:24:23 +0200 Subject: [PATCH] 0-key multi press is now 0-key double press (because this is what makes sense) --- docs/user-manual.md | 2 +- res/values-bg/strings.xml | 2 +- res/values-es/strings.xml | 2 +- res/values-fr/strings.xml | 2 +- res/values-ru/strings.xml | 2 +- res/values-uk/strings.xml | 2 +- res/values/strings.xml | 2 +- .../github/sspanak/tt9/ime/TraditionalT9.java | 16 +- .../sspanak/tt9/ime/modes/InputMode.java | 14 +- .../sspanak/tt9/ime/modes/ModePredictive.java | 247 ++++++++++-------- .../tt9/preferences/SettingsStore.java | 7 +- .../items/ItemSelectZeroKeyCharacter.java | 4 +- 12 files changed, 166 insertions(+), 136 deletions(-) diff --git a/docs/user-manual.md b/docs/user-manual.md index fa476930..7431760c 100644 --- a/docs/user-manual.md +++ b/docs/user-manual.md @@ -60,7 +60,7 @@ _Predictive mode only._ - **Hold:** type "0". - **In Predictive mode:** - **Press:** type space, newline or special/math characters. - - **Multiple Press:** type multiple spaces. + - **Double Press:** type the character assigned in Predictive mode settings. (Default: ".") - **Hold:** type "0". #### 1- to 9-key: diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index 025917fa..dbbb4281 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -46,7 +46,7 @@ Подсказващ режим Няма речник за език „%1$s“. Заредете го в Настройки. Клавиатура - Символ при многократно натисната \"0\" + Символ при двойно натисната \"0\" Нов ред Интервал Напишете дума… diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index a4d0a3a0..420dfae7 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -28,7 +28,7 @@ Escribir la primera letra de cada frase en mayúscula. Espacio automático Insertar un espacio automático después des palabras y signos de puntuación. - Carácter cuando se presiona \"0\" varias veces + Carácter cuando se presiona \"0\" dos veces Teclado en pantalla Diccionario cargado con éxito. Orden de teclas inverso diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 9ac2f3c7..f841a162 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -39,7 +39,7 @@ Clavier Espace Nouvelle ligne - Caractère lorsque «0» est appuyé plusieurs fois + Caractère lorsque «0» est appuyé deux fois Tapez un mot… Inverser l\'ordre des clés Activez le paramètre s\'il y a 7–8–9 sur le premier rang, au lieu de 1–2–3. diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index c2fb58fb..0dbb7d23 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -35,7 +35,7 @@ Автоматически добавлять пробел после слов и знаков препинания. Авто заглавные буквы Автоматически начинать предложение с заглавной буквы. - Символ при многократном нажатии клавиши 0 + Символ при двойном нажатии клавиши 0 Кнопки на экране Не удалось загрузить словарь. Проблема в слове «%1$s» в строке %2$d для языка «%3$s». Отсутствует словарь для языка «%1$s». Вы можете загрузить его в Настройках. diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 3b754668..9399cb6e 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -34,7 +34,7 @@ Автоматично додавати пробіл після слів і розділових знаків. Авто заголовні букви Автоматично починати речення з заголовної букви. - Символ при багаторазовому натисканні клавіші 0 + Символ при подвійному натисканні клавіші 0 Кнопки на екрані Назад Виклик diff --git a/res/values/strings.xml b/res/values/strings.xml index c0e71431..f17a3be8 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -26,7 +26,7 @@ Automatically start sentences with a capital letter. Languages Dark Theme - Character for Multiple 0-key Press + Character for Double 0-key Press Show On-Screen Keys Help Reverse Key Order diff --git a/src/io/github/sspanak/tt9/ime/TraditionalT9.java b/src/io/github/sspanak/tt9/ime/TraditionalT9.java index 4a005055..7da8fdfd 100644 --- a/src/io/github/sspanak/tt9/ime/TraditionalT9.java +++ b/src/io/github/sspanak/tt9/ime/TraditionalT9.java @@ -166,7 +166,7 @@ public class TraditionalT9 extends KeyPadHandler { mInputMode.onAcceptSuggestion(mLanguage, word); commitCurrentSuggestion(); - autoCorrectSpace(word, true, -1, false); + autoCorrectSpace(word, true, -1, false, false); resetKeyRepeat(); return true; @@ -235,7 +235,7 @@ public class TraditionalT9 extends KeyPadHandler { if (mInputMode.shouldAcceptCurrentSuggestion(mLanguage, key, hold, repeat > 0)) { mInputMode.onAcceptSuggestion(mLanguage, currentWord); commitCurrentSuggestion(false); - autoCorrectSpace(currentWord, false, key, hold); + autoCorrectSpace(currentWord, false, key, hold, repeat > 0); currentWord = ""; } @@ -255,7 +255,13 @@ public class TraditionalT9 extends KeyPadHandler { } if (mInputMode.getWord() != null) { - commitText(mInputMode.getWord()); + currentWord = mInputMode.getWord(); + + mInputMode.onAcceptSuggestion(mLanguage, currentWord); + commitText(currentWord); + clearSuggestions(); + autoCorrectSpace(currentWord, true, key, hold, repeat > 0); + resetKeyRepeat(); } else { getSuggestions(); } @@ -560,12 +566,12 @@ public class TraditionalT9 extends KeyPadHandler { } - private void autoCorrectSpace(String currentWord, boolean isWordAcceptedManually, int incomingKey, boolean hold) { + private void autoCorrectSpace(String currentWord, boolean isWordAcceptedManually, int incomingKey, boolean hold, boolean repeat) { if (mInputMode.shouldDeletePrecedingSpace(inputField)) { InputFieldHelper.deletePrecedingSpace(currentInputConnection, currentWord); } - if (mInputMode.shouldAddAutoSpace(currentInputConnection, inputField, isWordAcceptedManually, incomingKey, hold)) { + if (mInputMode.shouldAddAutoSpace(currentInputConnection, inputField, isWordAcceptedManually, incomingKey, hold, repeat)) { commitText(" "); } } diff --git a/src/io/github/sspanak/tt9/ime/modes/InputMode.java b/src/io/github/sspanak/tt9/ime/modes/InputMode.java index 46915ab7..0a37c460 100644 --- a/src/io/github/sspanak/tt9/ime/modes/InputMode.java +++ b/src/io/github/sspanak/tt9/ime/modes/InputMode.java @@ -74,8 +74,14 @@ abstract public class InputMode { abstract public int getId(); abstract public int getSequenceLength(); // The number of key presses for the current word. - public boolean shouldAddAutoSpace(InputConnection inputConnection, EditorInfo inputField, boolean isWordAcceptedManually, int incomingKey, boolean hold) { return false; } + // Interaction with the IME. Return "true" if it should perform the respective action. + public boolean shouldAcceptCurrentSuggestion(Language language, int key, boolean hold, boolean repeat) { return false; } + public boolean shouldAddAutoSpace(InputConnection inputConnection, EditorInfo inputField, boolean isWordAcceptedManually, int incomingKey, boolean hold, boolean repeat) { return false; } public boolean shouldDeletePrecedingSpace(EditorInfo inputField) { return false; } + public boolean shouldSelectNextSuggestion() { return false; } + public boolean shouldTrackNumPress() { return true; } + public boolean shouldTrackUpDown() { return false; } + public boolean shouldTrackLeftRight() { return false; } public void reset() { suggestions = new ArrayList<>(); @@ -118,10 +124,4 @@ abstract public class InputMode { public boolean isStemFilterFuzzy() { return false; } public String getWordStem() { return ""; } public boolean setWordStem(Language language, String stem, boolean exact) { return false; } - - public boolean shouldTrackNumPress() { return true; } - public boolean shouldTrackUpDown() { return false; } - public boolean shouldTrackLeftRight() { return false; } - public boolean shouldAcceptCurrentSuggestion(Language language, int key, boolean hold, boolean repeat) { return false; } - public boolean shouldSelectNextSuggestion() { return false; } } diff --git a/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java b/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java index f94e2275..095e27af 100644 --- a/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java +++ b/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java @@ -13,6 +13,7 @@ import io.github.sspanak.tt9.Logger; import io.github.sspanak.tt9.db.DictionaryDb; import io.github.sspanak.tt9.ime.EmptyDatabaseWarning; import io.github.sspanak.tt9.ime.helpers.InputFieldHelper; +import io.github.sspanak.tt9.languages.InvalidLanguageCharactersException; import io.github.sspanak.tt9.languages.Language; import io.github.sspanak.tt9.languages.Punctuation; import io.github.sspanak.tt9.preferences.SettingsStore; @@ -81,15 +82,13 @@ public class ModePredictive extends InputMode { @Override - public boolean onNumber(Language l, int key, boolean hold, int repeat) { + public boolean onNumber(Language language, int key, boolean hold, int repeat) { if (hold) { // hold to type any digit reset(); word = String.valueOf(key); } else if (key == 0 && repeat > 0) { - // repeat "0" is a shortcut for the preferred character (default: space) - reset(); - word = settings.getDoubleZeroChar(); + onDouble0(language); } else { // words super.reset(); @@ -100,6 +99,23 @@ public class ModePredictive extends InputMode { } + /** + * onDouble0 + * Double "0" is a shortcut for the preferred character. + */ + private void onDouble0(Language language) { + try { + reset(); + word = settings.getDoubleZeroChar(); + digitSequence = language.getDigitSequenceForWord(word); + } catch (InvalidLanguageCharactersException e) { + Logger.w("tt9/onDouble0", "Failed getting the sequence for word: '" + word + "'. Performing standard 0-key action."); + reset(); + digitSequence = "0"; + } + } + + @Override public void reset() { super.reset(); @@ -108,113 +124,6 @@ public class ModePredictive extends InputMode { } - /** - * shouldAddAutoSpace - * When the "auto-space" settings is enabled, this determines whether to automatically add a space - * at the end of a sentence or after accepting a suggestion. This allows faster typing, without - * pressing space. - * - * See the helper functions for the list of rules. - */ - @Override - public boolean shouldAddAutoSpace(InputConnection inputConnection, EditorInfo inputField, boolean isWordAcceptedManually, int incomingKey, boolean hold) { - return - settings.getAutoSpace() - && !hold - && ( - shouldAddAutoSpaceAfterPunctuation(inputField, incomingKey) - || shouldAddAutoSpaceAfterWord(inputField, isWordAcceptedManually) - ) - && !InputFieldHelper.isThereSpaceAhead(inputConnection); - } - - - /** - * shouldDeletePrecedingSpace - * When the "auto-space" settings is enabled, determine whether to delete spaces before punctuation. - * This allows automatic conversion from: "words ." to: "words." - */ - @Override - public boolean shouldDeletePrecedingSpace(EditorInfo inputField) { - return - settings.getAutoSpace() - && ( - lastAcceptedWord.equals(".") - || lastAcceptedWord.equals(",") - || lastAcceptedWord.equals(";") - || lastAcceptedWord.equals(":") - || lastAcceptedWord.equals("!") - || lastAcceptedWord.equals("?") - || lastAcceptedWord.equals(")") - || lastAcceptedWord.equals("]") - || lastAcceptedWord.equals("'") - || lastAcceptedWord.equals("@") - ) - && !InputFieldHelper.isSpecializedTextField(inputField); - } - - - /** - * shouldAddAutoSpaceAfterPunctuation - * Determines whether to automatically adding a space after certain punctuation signs makes sense. - * The rules are similar to the ones in the standard Android keyboard (with some exceptions, - * because we are not using a QWERTY keyboard here). - */ - private boolean shouldAddAutoSpaceAfterPunctuation(EditorInfo inputField, int incomingKey) { - return - incomingKey != 0 - && ( - lastAcceptedWord.endsWith(".") - || lastAcceptedWord.endsWith(",") - || lastAcceptedWord.endsWith(";") - || lastAcceptedWord.endsWith(":") - || lastAcceptedWord.endsWith("!") - || lastAcceptedWord.endsWith("?") - || lastAcceptedWord.endsWith(")") - || lastAcceptedWord.endsWith("]") - || lastAcceptedWord.endsWith("%") - ) - && !InputFieldHelper.isSpecializedTextField(inputField); - } - - - /** - * shouldAddAutoSpaceAfterPunctuation - * Similar to "shouldAddAutoSpaceAfterPunctuation()", but determines whether to add a space after - * words. - */ - private boolean shouldAddAutoSpaceAfterWord(EditorInfo inputField, boolean isWordAcceptedManually) { - return - // Do not add space when auto-accepting words, because it feels very confusing when typing. - isWordAcceptedManually - // Secondary punctuation - && !lastAcceptedSequence.equals("0") - // Emoji - && !lastAcceptedSequence.startsWith("1") - && !InputFieldHelper.isSpecializedTextField(inputField); - } - - - /** - * shouldAcceptCurrentSuggestion - * In this mode, In addition to confirming the suggestion in the input field, - * we also increase its' priority. This function determines whether we want to do all this or not. - */ - @Override - public boolean shouldAcceptCurrentSuggestion(Language language, int key, boolean hold, boolean repeat) { - return - hold - // Quickly accept suggestions using "space" instead of pressing "ok" then "space" - || key == 0 - // Punctuation is considered "a word", so that we can increase the priority as needed - // Also, it must break the current word. - || (!language.isPunctuationPartOfWords() && key == 1 && digitSequence.length() > 0 && !digitSequence.endsWith("1")) - // On the other hand, letters also "break" punctuation. - || (!language.isPunctuationPartOfWords() && key != 1 && digitSequence.endsWith("1")) - || (digitSequence.endsWith("0")); - } - - /** * clearWordStem * Do not filter the suggestions by the word set using "setWordStem()", use only the digit sequence. @@ -284,6 +193,7 @@ public class ModePredictive extends InputMode { return isStemFuzzy; } + /** * loadStaticSuggestions * Similar to "loadSuggestions()", but loads suggestions that are not in the database. @@ -493,7 +403,7 @@ public class ModePredictive extends InputMode { // emoji and punctuation are not in the database, so there is no point in // running queries that would update nothing - if (!sequence.startsWith("11") && !sequence.equals("1") && !sequence.equals("0")) { + if (!sequence.startsWith("11") && !sequence.equals("1") && !sequence.startsWith("0")) { DictionaryDb.incrementWordFrequency(language, currentWord, sequence); } } catch (Exception e) { @@ -572,8 +482,117 @@ public class ModePredictive extends InputMode { super.nextTextCase(); } - @Override final public boolean isPredictive() { return true; } - @Override public int getSequenceLength() { return digitSequence.length(); } + + /** + * shouldAcceptCurrentSuggestion + * In this mode, In addition to confirming the suggestion in the input field, + * we also increase its' priority. This function determines whether we want to do all this or not. + */ + @Override + public boolean shouldAcceptCurrentSuggestion(Language language, int key, boolean hold, boolean repeat) { + return + hold + // Quickly accept suggestions using "space" instead of pressing "ok" then "space" + || (key == 0 && !repeat) + // Punctuation is considered "a word", so that we can increase the priority as needed + // Also, it must break the current word. + || (!language.isPunctuationPartOfWords() && key == 1 && digitSequence.length() > 0 && !digitSequence.endsWith("1")) + // On the other hand, letters also "break" punctuation. + || (!language.isPunctuationPartOfWords() && key != 1 && digitSequence.endsWith("1")) + || (digitSequence.endsWith("0") && key != 0); + } + + + /** + * shouldAddAutoSpace + * When the "auto-space" settings is enabled, this determines whether to automatically add a space + * at the end of a sentence or after accepting a suggestion. This allows faster typing, without + * pressing space. + * + * See the helper functions for the list of rules. + */ + @Override + public boolean shouldAddAutoSpace(InputConnection inputConnection, EditorInfo inputField, boolean isWordAcceptedManually, int incomingKey, boolean hold, boolean repeat) { + return + settings.getAutoSpace() + && !hold + && ( + shouldAddAutoSpaceAfterPunctuation(inputField, incomingKey, repeat) + || shouldAddAutoSpaceAfterWord(inputField, isWordAcceptedManually) + ) + && !InputFieldHelper.isThereSpaceAhead(inputConnection); + } + + + /** + * shouldAddAutoSpaceAfterPunctuation + * Determines whether to automatically adding a space after certain punctuation signs makes sense. + * The rules are similar to the ones in the standard Android keyboard (with some exceptions, + * because we are not using a QWERTY keyboard here). + */ + private boolean shouldAddAutoSpaceAfterPunctuation(EditorInfo inputField, int incomingKey, boolean repeat) { + return + (incomingKey != 0 || repeat) + && ( + lastAcceptedWord.endsWith(".") + || lastAcceptedWord.endsWith(",") + || lastAcceptedWord.endsWith(";") + || lastAcceptedWord.endsWith(":") + || lastAcceptedWord.endsWith("!") + || lastAcceptedWord.endsWith("?") + || lastAcceptedWord.endsWith(")") + || lastAcceptedWord.endsWith("]") + || lastAcceptedWord.endsWith("%") + ) + && !InputFieldHelper.isSpecializedTextField(inputField); + } + + + /** + * shouldAddAutoSpaceAfterPunctuation + * Similar to "shouldAddAutoSpaceAfterPunctuation()", but determines whether to add a space after + * words. + */ + private boolean shouldAddAutoSpaceAfterWord(EditorInfo inputField, boolean isWordAcceptedManually) { + return + // Do not add space when auto-accepting words, because it feels very confusing when typing. + isWordAcceptedManually + // Secondary punctuation + && !lastAcceptedSequence.equals("0") + // Emoji + && !lastAcceptedSequence.startsWith("1") + && !InputFieldHelper.isSpecializedTextField(inputField); + } + + + /** + * shouldDeletePrecedingSpace + * When the "auto-space" settings is enabled, determine whether to delete spaces before punctuation. + * This allows automatic conversion from: "words ." to: "words." + */ + @Override + public boolean shouldDeletePrecedingSpace(EditorInfo inputField) { + return + settings.getAutoSpace() + && ( + lastAcceptedWord.equals(".") + || lastAcceptedWord.equals(",") + || lastAcceptedWord.equals(";") + || lastAcceptedWord.equals(":") + || lastAcceptedWord.equals("!") + || lastAcceptedWord.equals("?") + || lastAcceptedWord.equals(")") + || lastAcceptedWord.equals("]") + || lastAcceptedWord.equals("'") + || lastAcceptedWord.equals("@") + ) + && !InputFieldHelper.isSpecializedTextField(inputField); + } + + @Override public boolean shouldTrackUpDown() { return true; } @Override public boolean shouldTrackLeftRight() { return true; } + + @Override final public boolean isPredictive() { return true; } + @Override public int getSequenceLength() { return digitSequence.length(); } } diff --git a/src/io/github/sspanak/tt9/preferences/SettingsStore.java b/src/io/github/sspanak/tt9/preferences/SettingsStore.java index c878eb84..419c8a9f 100644 --- a/src/io/github/sspanak/tt9/preferences/SettingsStore.java +++ b/src/io/github/sspanak/tt9/preferences/SettingsStore.java @@ -209,7 +209,12 @@ public class SettingsStore { public boolean getAutoSpace() { return prefs.getBoolean("auto_space", false); } public boolean getAutoTextCase() { return prefs.getBoolean("auto_text_case", true); } - public String getDoubleZeroChar() { return prefs.getString("pref_double_zero_char", " "); } + public String getDoubleZeroChar() { + String character = prefs.getString("pref_double_zero_char", "."); + + // SharedPreferences return a corrupted string when using the real "\n"... :( + return character.equals("\\n") ? "\n" : character; + } public boolean getUpsideDownKeys() { return prefs.getBoolean("pref_upside_down_keys", false); } diff --git a/src/io/github/sspanak/tt9/preferences/items/ItemSelectZeroKeyCharacter.java b/src/io/github/sspanak/tt9/preferences/items/ItemSelectZeroKeyCharacter.java index 5dfb0094..a8a6dce3 100644 --- a/src/io/github/sspanak/tt9/preferences/items/ItemSelectZeroKeyCharacter.java +++ b/src/io/github/sspanak/tt9/preferences/items/ItemSelectZeroKeyCharacter.java @@ -21,9 +21,9 @@ public class ItemSelectZeroKeyCharacter { Resources resources = context.getResources(); - KEYS.put(" ", resources.getString(R.string.char_space)); - KEYS.put("\n", resources.getString(R.string.char_newline)); KEYS.put(".", resources.getString(R.string.char_dot)); + KEYS.put("\\n", resources.getString(R.string.char_newline)); // SharedPreferences return a corrupted string when using the real "\n"... :( + KEYS.put(" ", resources.getString(R.string.char_space)); }