Recomposition (#609)
* word re-composition function * reordered the Keypad settings a bit
This commit is contained in:
parent
0228c5fd81
commit
7195688867
20 changed files with 137 additions and 20 deletions
|
|
@ -1,6 +1,5 @@
|
|||
package io.github.sspanak.tt9.ime;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
|
|
@ -132,10 +131,13 @@ public abstract class TypingHandler extends KeyPadHandler {
|
|||
suggestionOps.commitCurrent(false);
|
||||
mInputMode.reset();
|
||||
|
||||
int repeats = hold ? Math.min(Math.max(textField.getWordBeforeCursorLength(), 1), SettingsStore.BACKSPACE_ACCELERATION_MAX_CHARS) : 1;
|
||||
for (int i = repeats; i > 0; i--) {
|
||||
super.sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
|
||||
int prevChars = hold ? Math.min(Math.max(textField.getPaddedWordBeforeCursorLength(), 1), SettingsStore.BACKSPACE_ACCELERATION_MAX_CHARS) : 1;
|
||||
textField.deleteChars(prevChars);
|
||||
}
|
||||
|
||||
if (!hold && suggestionOps.isEmpty() && mInputMode.recompose(textField.getWordBeforeCursor())) {
|
||||
textField.deleteChars(mInputMode.getSequenceLength());
|
||||
getSuggestions();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -289,7 +291,7 @@ public abstract class TypingHandler extends KeyPadHandler {
|
|||
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd);
|
||||
textSelection.onSelectionUpdate(newSelStart, newSelEnd);
|
||||
|
||||
// in case the app has modified the InputField and moved the cursor without notifiying us...
|
||||
// in case the app has modified the InputField and moved the cursor without notifying us...
|
||||
if (appHacks.onUpdateSelection(mInputMode, suggestionOps, oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,12 +104,29 @@ public class TextField extends InputField {
|
|||
}
|
||||
|
||||
|
||||
@NonNull public String getWordBeforeCursor() {
|
||||
if (getTextAfterCursor(1).startsWithWord()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String before = getStringBeforeCursor();
|
||||
if (before.isEmpty() || !Character.isAlphabetic(before.charAt(before.length() - 1))) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int lastSpace = Math.max(before.lastIndexOf(' ') + 1, 0);
|
||||
int length = Math.max(before.length(), lastSpace);
|
||||
|
||||
return before.substring(lastSpace, length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the length of the word before the cursor. If the cursor is inside a word, 0 is returned,
|
||||
* because there is no full word before it. The scanning length is up to the maximum returned by
|
||||
* getTextBeforeCursor().
|
||||
* Returns the length of the first word before the cursor including any whitespace after it.
|
||||
* If the cursor is inside a word, 0 is returned, because there is no full word before it.
|
||||
* The scanning length is up to the maximum returned by getTextBeforeCursor().
|
||||
*/
|
||||
public int getWordBeforeCursorLength() {
|
||||
public int getPaddedWordBeforeCursorLength() {
|
||||
if (getTextAfterCursor(1).startsWithWord()) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -124,6 +141,20 @@ public class TextField extends InputField {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes one character by emulating a backspace key event (useful for deleting emoji and Unicode
|
||||
* characters); Or deletes a region of text at once (faster, but may leave half a surrogate pair).
|
||||
*/
|
||||
public void deleteChars(int numberOfChars) {
|
||||
if (numberOfChars == 1) {
|
||||
connection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
|
||||
connection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
|
||||
} else if (numberOfChars > 1) {
|
||||
connection.deleteSurroundingText(numberOfChars, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* deletePrecedingSpace
|
||||
* Deletes the preceding space before the given word. The word must be before the cursor.
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ abstract public class InputMode {
|
|||
public boolean shouldDeletePrecedingSpace(InputType inputType) { return false; }
|
||||
public boolean shouldIgnoreText(String text) { return text == null || text.isEmpty(); }
|
||||
public boolean shouldSelectNextSuggestion() { return false; }
|
||||
public boolean recompose(String word) { return false; }
|
||||
|
||||
public void reset() {
|
||||
autoAcceptTimeout = -1;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import io.github.sspanak.tt9.languages.EmojiLanguage;
|
|||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||
import io.github.sspanak.tt9.languages.NaturalLanguage;
|
||||
import io.github.sspanak.tt9.languages.exceptions.InvalidLanguageCharactersException;
|
||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||
import io.github.sspanak.tt9.util.Characters;
|
||||
import io.github.sspanak.tt9.util.Logger;
|
||||
|
|
@ -123,6 +124,27 @@ public class ModePredictive extends InputMode {
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean recompose(String word) {
|
||||
if (!settings.getBackspaceRecomposing() || word == null || word.length() < 2 || word.contains(" ")) {
|
||||
Logger.d(LOG_TAG, "Not recomposing invalid word: '" + word + "'");
|
||||
textCase = CASE_CAPITALIZE;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
reset();
|
||||
digitSequence = language.getDigitSequenceForWord(word);
|
||||
textCase = new Text(language, word).getTextCase();
|
||||
setWordStem(word, true);
|
||||
} catch (InvalidLanguageCharactersException e) {
|
||||
Logger.d(LOG_TAG, "Not recomposing word: '" + word + "'. " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
|
|
@ -246,7 +268,7 @@ public class ModePredictive extends InputMode {
|
|||
.setIsStemFuzzy(isStemFuzzy)
|
||||
.setStem(stem)
|
||||
.setLanguage(searchLanguage)
|
||||
.setInputWord(currentWord)
|
||||
.setInputWord(currentWord.isEmpty() ? stem : currentWord)
|
||||
.setWordsChangedHandler(this::onPredictions)
|
||||
.load();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ class SettingsTyping extends SettingsInput {
|
|||
return prefs.getBoolean("backspace_acceleration", false);
|
||||
}
|
||||
|
||||
public boolean getBackspaceRecomposing() {
|
||||
return prefs.getBoolean("backspace_recomposing", true);
|
||||
}
|
||||
|
||||
public String getDoubleZeroChar() {
|
||||
String character = prefs.getString("pref_double_zero_char", ".");
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import androidx.annotation.NonNull;
|
|||
|
||||
import java.util.Locale;
|
||||
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
|
||||
public class Text extends TextTools {
|
||||
|
|
@ -36,11 +37,39 @@ public class Text extends TextTools {
|
|||
return text != null && !text.isEmpty() && Characters.isGraphic(text.charAt(text.length() - 1));
|
||||
}
|
||||
|
||||
public int getTextCase() {
|
||||
if (isUpperCase()) {
|
||||
return InputMode.CASE_UPPER;
|
||||
} else if (isCapitalized()) {
|
||||
return InputMode.CASE_CAPITALIZE;
|
||||
} else if (isMixedCase()) {
|
||||
return InputMode.CASE_DICTIONARY;
|
||||
} else {
|
||||
return InputMode.CASE_LOWER;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return text == null || text.isEmpty();
|
||||
}
|
||||
|
||||
private boolean isCapitalized() {
|
||||
if (text == null || text.length() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Character.isUpperCase(text.charAt(0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 1, end = text.length(); i < end; i++) {
|
||||
if (Character.isUpperCase(text.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isMixedCase() {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
<string name="pref_dark_theme">Тъмен облик</string>
|
||||
<string name="pref_auto_capitals_after_newline">Автоматични главни букви на всеки ред</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">Започвай всеки ред с главна буква, дори и да е в средата на изречение.</string>
|
||||
<string name="pref_backspace_recomposing">Редактиране на думи</string>
|
||||
<string name="pref_backspace_recomposing_summary">Връщай списъка с предложения при натискане на Backspace на края на дума.\n(Не работи в някои приложения.)</string>
|
||||
<string name="pref_choose_languages">Езици</string>
|
||||
<string name="dictionary_truncate_title">Изтрий всички</string>
|
||||
<string name="pref_status_icon">Икона за състояние</string>
|
||||
|
|
|
|||
|
|
@ -37,8 +37,9 @@
|
|||
<string name="pref_auto_text_case_summary">Automatisch Sätze mit einem Großbuchstaben beginnen.</string>
|
||||
<string name="pref_auto_capitals_after_newline">Automatische Großbuchstaben auf jeder Zeile</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">Jede Zeile mit einem Großbuchstaben beginnen, auch wenn es mitten im Satz ist.</string>
|
||||
<string name="pref_backspace_recomposing">Wortnachbearbeitung</string>
|
||||
<string name="pref_backspace_recomposing_summary">Die Vorschlagsliste zurückbringen, indem Sie am Ende eines Wortes die Rücktaste drücken.\n(Nicht in allen Apps unterstützt)</string>
|
||||
<string name="pref_choose_languages">Sprachen</string>
|
||||
|
||||
<string name="pref_status_icon">Statusicon</string>
|
||||
<string name="pref_status_icon_summary">Ein Icon anzeigen, wenn die Tastatureingabe aktiv ist.</string>
|
||||
<string name="pref_upside_down_keys">Die Reihenfolge der Tasten umkehren</string>
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
<string name="pref_category_keypad">Teclado</string>
|
||||
<string name="pref_auto_capitals_after_newline">Mayúsculas automáticas en cada línea</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">Comenzar cada línea con una letra mayúscula, incluso si está en medio de una oración.</string>
|
||||
<string name="pref_backspace_recomposing">Recomposición de palabras</string>
|
||||
<string name="pref_backspace_recomposing_summary">Recuperar la lista de sugerencias presionando la tecla Retroceso al final de una palabra.\n(No compatible con algunas aplicaciones)</string>
|
||||
<string name="pref_choose_languages">Idiomas</string>
|
||||
<string name="pref_dark_theme">Tema oscuro</string>
|
||||
<string name="char_space">Espacio</string>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
<string name="pref_dark_theme">Thème sombre</string>
|
||||
<string name="pref_auto_capitals_after_newline">Majuscules automatiques sur chaque ligne</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">Commencer chaque ligne avec une majuscule, même si elle est au milieu d\'une phrase.</string>
|
||||
<string name="pref_backspace_recomposing">Recomposition de mots</string>
|
||||
<string name="pref_backspace_recomposing_summary">Ramener la liste de suggestions en appuyant sur Retour arrière à la fin d\'un mot.\n(Non pris en charge dans certaines applications)</string>
|
||||
<string name="pref_choose_languages">Langues</string>
|
||||
<string name="dictionary_truncate_title">Supprimer tous</string>
|
||||
<string name="pref_status_icon">Icône d\'état</string>
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@
|
|||
<string name="pref_auto_text_case_summary">Iniziare automaticamente le frasi con una lettera maiuscola.</string>
|
||||
<string name="pref_auto_capitals_after_newline">Maiuscole automatiche su ogni riga</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">Iniziare ogni riga con una lettera maiuscola, anche se è nel mezzo di una frase.</string>
|
||||
<string name="pref_backspace_recomposing">Ricomposizione delle parole</string>
|
||||
<string name="pref_backspace_recomposing_summary">Riportare l\'elenco dei suggerimenti premendo Backspace alla fine di una parola.\n(Non supportato in alcune app)</string>
|
||||
<string name="pref_choose_languages">Lingue</string>
|
||||
|
||||
<string name="pref_status_icon">Icona di stato</string>
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
<string name="pref_auto_text_case_summary">התחל אוטומטית משפטים באות גדולה.</string>
|
||||
<string name="pref_auto_capitals_after_newline">רישיות אוטומטיות בכל שורה</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">להתחיל כל שורה באות ראשונה גדולה, גם אם היא באמצע משפט.</string>
|
||||
<string name="pref_backspace_recomposing">עריכת מילים</string>
|
||||
<string name="pref_backspace_recomposing_summary">להחזיר את רשימת ההצעות על ידי לחיצה על מקש Backspace בסוף מילה.\n(לא נתמך בחלק מהאפליקציות)</string>
|
||||
<string name="pref_choose_languages">שפות</string>
|
||||
<string name="pref_dark_theme">ערכת נושא שחורה</string>
|
||||
<string name="pref_double_zero_char">תו ללחיצה מרובה על מקש 0</string>
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
<string name="pref_auto_text_case_summary">Automatiškai pradėti sakinius didžiąja raide.</string>
|
||||
<string name="pref_auto_capitals_after_newline">Automatiniai didžiosios raidės kiekvienoje eilutėje</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">Pradėti kiekvieną eilutę didžiąja raide, net jei ji yra sakinio viduryje.</string>
|
||||
<string name="pref_backspace_recomposing">Žodžių redagavimas</string>
|
||||
<string name="pref_backspace_recomposing_summary">Sugrąžinti siūlymų sąrašą paspaudžiant klavišą Backspace žodžio pabaigoje.\n(Nepalaikoma kai kuriose programėlėse)</string>
|
||||
<string name="pref_choose_languages">Kalbos</string>
|
||||
<string name="pref_dark_theme">Tamsi išvaizda</string>
|
||||
<string name="pref_dark_theme_yes">Taip</string>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
<string name="pref_auto_text_case_summary">Automatisch zinnen beginnen met een hoofdletter.</string>
|
||||
<string name="pref_auto_capitals_after_newline">Automatische hoofdletters op elke regel</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">Elke regel beginnen met een hoofdletter, zelfs als het midden van een zin is.</string>
|
||||
<string name="pref_backspace_recomposing">Woordherbewerking</string>
|
||||
<string name="pref_backspace_recomposing_summary">Breng de suggestielijst terug door Backspace te drukken aan het einde van een woord.\n(Niet ondersteund in sommige apps)</string>
|
||||
<string name="pref_choose_languages">Talen</string>
|
||||
<string name="pref_status_icon">Statusicoon</string>
|
||||
<string name="pref_status_icon_summary">Een icoon tonen wanneer toetsenbordinvoer actief is.</string>
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@
|
|||
<string name="pref_auto_text_case_summary">Iniciar automaticamente as frases com letras maiúsculas.</string>
|
||||
<string name="pref_auto_capitals_after_newline">Letras maiúsculas automáticas em cada linha</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">Começar cada linha com uma letra maiúscula, mesmo que esteja no meio de uma frase.</string>
|
||||
<string name="pref_backspace_recomposing">Recomposição de palavras</string>
|
||||
<string name="pref_backspace_recomposing_summary">Trazer de volta a lista de sugestões pressionando Backspace no final de uma palavra.\n(Não suportado em alguns aplicativos)</string>
|
||||
<string name="pref_choose_languages">Idiomas</string>
|
||||
<string name="pref_dark_theme">Modo Escuro</string>
|
||||
<string name="pref_double_zero_char">Caractere para toque duplo na tecla 0</string>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
<string name="pref_dark_theme">Темная тема</string>
|
||||
<string name="pref_auto_capitals_after_newline">Автоматические заглавные буквы на каждой строке</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">Начинать каждую строку с заглавной буквы, даже если она в середине предложения.</string>
|
||||
<string name="pref_backspace_recomposing">Редактирование слов</string>
|
||||
<string name="pref_backspace_recomposing_summary">Вернуть список предложений, нажав клавишу Backspace в конце слова.\n(Не поддерживается в некоторых приложениях)</string>
|
||||
<string name="pref_choose_languages">Языки</string>
|
||||
<string name="dictionary_truncate_title">Удалить все</string>
|
||||
<string name="pref_status_icon">Иконка состояния</string>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
<string name="pref_auto_text_case_summary">Cümlelere otomatik olarak büyük harfle başlar.</string>
|
||||
<string name="pref_auto_capitals_after_newline">Her Satıra Büyük Harf ile Başlama</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">Cümlenin ortasında olsa bile her yeni satıra büyük harf ile başlar.</string>
|
||||
<string name="pref_backspace_recomposing">Kelime Yeniden Düzenleme</string>
|
||||
<string name="pref_backspace_recomposing_summary">Kelimenin sonunda Geri tuşuna basarak öneri listesini geri getirmek.\n(Bazı uygulamalarda desteklenmez)</string>
|
||||
<string name="pref_choose_languages">Diller</string>
|
||||
|
||||
<string name="pref_status_icon">Durum</string>
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@
|
|||
<string name="pref_auto_text_case_summary">Автоматично починати речення з великої букви</string>
|
||||
<string name="pref_auto_capitals_after_newline">Автоматичні великі літери на кожному рядку</string>
|
||||
<string name="pref_auto_capitals_after_newline_summary">Починати кожен рядок з великої літери, навіть якщо він у середині речення.</string>
|
||||
<string name="pref_backspace_recomposing">Редагування слів</string>
|
||||
<string name="pref_backspace_recomposing_summary">Повернути список пропозицій, натиснувши клавішу Backspace в кінці слова.\n(Не підтримується в деяких додатках)</string>
|
||||
<string name="pref_choose_languages">Мови</string>
|
||||
<string name="pref_dark_theme">Темна тема</string>
|
||||
<string name="pref_dark_theme_yes">Так</string>
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@
|
|||
<string name="pref_auto_capitals_after_newline_summary">Start every line with a capital letter, even it is in the middle of a sentence.</string>
|
||||
<string name="pref_backspace_acceleration">Fast Delete</string>
|
||||
<string name="pref_backspace_acceleration_summary">Erase entire words by holding Backspace.\n(Not supported in some apps)</string>
|
||||
<string name="pref_backspace_recomposing">Word Re-composition</string>
|
||||
<string name="pref_backspace_recomposing_summary">Bring back the suggestion list by pressing Backspace at the end of a word. (Not supported in some apps)</string>
|
||||
<string name="pref_choose_languages">Languages</string>
|
||||
<string name="pref_dark_theme">Dark Theme</string>
|
||||
<string name="pref_dark_theme_yes">Yes</string>
|
||||
|
|
|
|||
|
|
@ -9,18 +9,16 @@
|
|||
app:key="screen_hotkeys"
|
||||
app:title="@string/pref_category_function_keys" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
app:key="pref_haptic_feedback"
|
||||
app:title="@string/pref_haptic_feedback"
|
||||
app:summary="@string/pref_haptic_feedback_summary"/>
|
||||
|
||||
<PreferenceCategory android:title="@string/function_backspace">
|
||||
<SwitchPreferenceCompat
|
||||
app:defaultValue="false"
|
||||
app:key="backspace_acceleration"
|
||||
app:title="@string/pref_backspace_acceleration"
|
||||
app:summary="@string/pref_backspace_acceleration_summary" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
app:key="pref_haptic_feedback"
|
||||
app:title="@string/pref_haptic_feedback"
|
||||
app:summary="@string/pref_haptic_feedback_summary"/>
|
||||
|
||||
<PreferenceCategory android:title="@string/pref_category_predictive_mode">
|
||||
|
||||
|
|
@ -43,6 +41,11 @@
|
|||
app:summary="@string/pref_auto_capitals_after_newline_summary"
|
||||
app:title="@string/pref_auto_capitals_after_newline" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
app:defaultValue="true"
|
||||
app:key="backspace_recomposing"
|
||||
app:title="@string/pref_backspace_recomposing"
|
||||
app:summary="@string/pref_backspace_recomposing_summary" />
|
||||
|
||||
<DropDownPreference
|
||||
app:defaultValue="."
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue