diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/AbstractHandler.java b/app/src/main/java/io/github/sspanak/tt9/ime/AbstractHandler.java index f14e68b6..2cb097c7 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/AbstractHandler.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/AbstractHandler.java @@ -11,7 +11,7 @@ import io.github.sspanak.tt9.util.Ternary; abstract public class AbstractHandler extends InputMethodService { // hardware key handlers abstract protected Ternary onBack(); - abstract public boolean onBackspace(); + abstract public boolean onBackspace(boolean hold); abstract public boolean onHotkey(int keyCode, boolean repeat, boolean validateOnly); abstract protected boolean onNumber(int key, boolean hold, int repeat); abstract public boolean onOK(); diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/KeyPadHandler.java b/app/src/main/java/io/github/sspanak/tt9/ime/KeyPadHandler.java index 21b41f83..124c592e 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/KeyPadHandler.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/KeyPadHandler.java @@ -60,7 +60,11 @@ abstract class KeyPadHandler extends UiHandler { // "backspace" key must repeat its function when held down, so we handle it in a special way if (Key.isBackspace(settings, keyCode)) { - if (onBackspace()) { + if ( + (settings.getBackspaceAcceleration() && event.getRepeatCount() > 0 && event.getRepeatCount() % SettingsStore.BACKSPACE_ACCELERATION_HARD_KEY_REPEAT_DEBOUNCE == 0 && onBackspace(true)) + || (settings.getBackspaceAcceleration() && event.getRepeatCount() > 0) + || onBackspace(false) + ) { return Key.setHandled(KeyEvent.KEYCODE_DEL, true); } else { Key.setHandled(KeyEvent.KEYCODE_DEL, false); diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/TypingHandler.java b/app/src/main/java/io/github/sspanak/tt9/ime/TypingHandler.java index cfc76270..9b27ca6f 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/TypingHandler.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/TypingHandler.java @@ -21,6 +21,7 @@ import io.github.sspanak.tt9.ime.modes.InputMode; import io.github.sspanak.tt9.ime.modes.ModePredictive; import io.github.sspanak.tt9.languages.Language; import io.github.sspanak.tt9.languages.LanguageCollection; +import io.github.sspanak.tt9.preferences.settings.SettingsStore; import io.github.sspanak.tt9.ui.UI; import io.github.sspanak.tt9.util.Text; @@ -110,7 +111,7 @@ public abstract class TypingHandler extends KeyPadHandler { @Override - public boolean onBackspace() { + public boolean onBackspace(boolean hold) { // Dialer fields seem to handle backspace on their own and we must ignore it, // otherwise, keyDown race condition occur for all keys. if (mInputMode.isPassthrough()) { @@ -125,11 +126,16 @@ public abstract class TypingHandler extends KeyPadHandler { suggestionOps.cancelDelayedAccept(); resetKeyRepeat(); - if (mInputMode.onBackspace()) { + if (!hold && mInputMode.onBackspace()) { getSuggestions(); } else { suggestionOps.commitCurrent(false); - super.sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); + 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); + } } return true; diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/helpers/TextField.java b/app/src/main/java/io/github/sspanak/tt9/ime/helpers/TextField.java index 637b0c5f..4ffa12de 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/helpers/TextField.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/helpers/TextField.java @@ -104,6 +104,26 @@ public class TextField extends InputField { } + /** + * 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(). + */ + public int getWordBeforeCursorLength() { + if (getTextAfterCursor(1).startsWithWord()) { + return 0; + } + + String before = getStringBeforeCursor(); + if (before.isEmpty()) { + return 0; + } + + int spaceShift = Math.max(before.lastIndexOf(' '), 0); + return before.length() - spaceShift; + } + + /** * deletePrecedingSpace * Deletes the preceding space before the given word. The word must be before the cursor. diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java index 62903891..17530565 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java @@ -102,7 +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 void reset() { autoAcceptTimeout = -1; specialCharSelectedGroup = -1; diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java index 2e193689..e1891b57 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java @@ -7,6 +7,9 @@ public class SettingsStore extends SettingsUI { public SettingsStore(Context context) { super(context); } /************* internal settings *************/ + public static final int BACKSPACE_ACCELERATION_MAX_CHARS = 10; + public static final int BACKSPACE_ACCELERATION_HARD_KEY_REPEAT_DEBOUNCE = 5; + public static final int BACKSPACE_ACCELERATION_SOFT_KEY_REPEAT_DEBOUNCE = 7; public final static int CLIPBOARD_PREVIEW_LENGTH = 20; public final static int CUSTOM_WORDS_IMPORT_MAX_LINES = 250; public final static int CUSTOM_WORDS_MAX = 1000; diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsTyping.java b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsTyping.java index 4fd2ad56..fcfa6cae 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsTyping.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsTyping.java @@ -15,6 +15,10 @@ class SettingsTyping extends SettingsInput { return getAutoTextCase() && prefs.getBoolean("auto_capitals_after_newline", false); } + public boolean getBackspaceAcceleration() { + return prefs.getBoolean("backspace_acceleration", false); + } + public String getDoubleZeroChar() { String character = prefs.getString("pref_double_zero_char", "."); diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftBackspaceKey.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftBackspaceKey.java index ff1fcd7e..da6c73ef 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftBackspaceKey.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftBackspaceKey.java @@ -6,10 +6,12 @@ import android.view.KeyEvent; import io.github.sspanak.tt9.R; import io.github.sspanak.tt9.languages.LanguageKind; +import io.github.sspanak.tt9.preferences.settings.SettingsStore; import io.github.sspanak.tt9.ui.Vibration; public class SoftBackspaceKey extends SoftKey { private boolean hold; + private int repeatCount = 0; public SoftBackspaceKey(Context context) { super(context); @@ -27,12 +29,23 @@ public class SoftBackspaceKey extends SoftKey { final protected boolean handlePress() { super.handlePress(); hold = false; - return deleteText(); + repeatCount = 0; + return validateTT9Handler() && deleteText(); } @Override final protected void handleHold() { hold = true; + + if ( + validateTT9Handler() + && tt9.getSettings().getBackspaceAcceleration() + && ++repeatCount < SettingsStore.BACKSPACE_ACCELERATION_SOFT_KEY_REPEAT_DEBOUNCE + ) { + return; + } + + repeatCount = 0; deleteText(); } @@ -44,7 +57,7 @@ public class SoftBackspaceKey extends SoftKey { } private boolean deleteText() { - if (validateTT9Handler() && !tt9.onBackspace()) { + if (!tt9.onBackspace(hold && tt9.getSettings().getBackspaceAcceleration())) { // Limited or special numeric field (e.g. formatted money or dates) cannot always return // the text length, therefore onBackspace() seems them as empty and does nothing. This results // in fallback to the default hardware key action. Here we simulate the hardware BACKSPACE. diff --git a/app/src/main/java/io/github/sspanak/tt9/util/Text.java b/app/src/main/java/io/github/sspanak/tt9/util/Text.java index b18bf945..91bfe6ee 100644 --- a/app/src/main/java/io/github/sspanak/tt9/util/Text.java +++ b/app/src/main/java/io/github/sspanak/tt9/util/Text.java @@ -95,9 +95,6 @@ public class Text extends TextTools { } - - - public boolean startsWithWhitespace() { return text != null && !text.isEmpty() && Character.isWhitespace(text.charAt(0)); } @@ -110,6 +107,10 @@ public class Text extends TextTools { return text != null && !text.isEmpty() && Characters.isGraphic(text.charAt(0)); } + public boolean startsWithWord() { + return text != null && !text.isEmpty() && Character.isAlphabetic(text.charAt(0)); + } + public String subStringEndingWord(boolean keepApostrophe, boolean keepQuote) { if (text == null) { return ""; diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 3003e6d0..b94a00ab 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -167,4 +167,6 @@ Избор на езици Търси езици думи + Бързо изтриване + Изтривай цели думи при задържане на Backspace.\n(Не работи в някои приложения.) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 9af34bd9..7ac929aa 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -156,4 +156,6 @@ Sprachen aktivieren Nach Sprachen suchen Wörter + Schnelles Löschen + Ganze Wörter löschen, indem Sie die Rücktaste gedrückt halten.\n(Nicht in allen Apps unterstützt) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index bfae2fb8..fed9419d 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -165,4 +165,6 @@ Habilitar idiomas Buscar idiomas palabras + Eliminación rápida + Borrar palabras completas manteniendo presionada la tecla Retroceso.\n(No compatible con algunas aplicaciones) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 8bafc96d..bc7c6244 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -163,4 +163,6 @@ Activer les langues Rechercher des langues mots + Suppression rapide + Effacer des mots entiers en maintenant la touche Retour arrière.\n(Non pris en charge dans certaines applications) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 14c7e58d..0522a7d5 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -155,5 +155,7 @@ Abilita lingue Cerca lingue parole + Cancellazione rapida + Cancellare intere parole tenendo premuto Backspace.\n(Non supportato in alcune app) diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index dfa3b184..cd6ea0e6 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -168,4 +168,6 @@ הפעל שפות חיפוש שפות מילים + מחיקה מהירה + למחוק מילים שלמות על ידי החזקת מקש Backspace.\n(לא נתמך בחלק מהאפליקציות) diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index c5f97211..bccba867 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -174,4 +174,6 @@ Įjungti kalbas Ieškoti kalbų žodžių + Greitas ištrynimas + Ištrinti visus žodžius laikant klavišą Backspace.\n(Nepalaikoma kai kuriose programėlėse) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 2ea31cef..d9ef5d90 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -154,4 +154,6 @@ Talen inschakelen Zoeken naar talen woorden + Snel verwijderen + Hele woorden wissen door Backspace ingedrukt te houden.\n(Niet ondersteund in sommige apps) diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 168bc4ec..89a7174b 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -36,9 +36,9 @@ Lento Método alternativo de rolagem de sugestões Ative se às vezes não conseguir ver todas as sugestões ou tiver problemas para rolá-las (Android 9 ou mais antigo). - Espaçamento Automático + Espaçamento automático Insere um espaçamento após ponto final. - Maiúsculas Automáticas + Maiúsculas automáticas Iniciar automaticamente as frases com letras maiúsculas. Letras maiúsculas automáticas em cada linha Começar cada linha com uma letra maiúscula, mesmo que esteja no meio de uma frase. @@ -168,4 +168,6 @@ Habilitar idiomas Buscar por idiomas palavras + Exclusão rápida + Apagar palavras inteiras segurando a tecla Backspace.\n(Não suportado em alguns aplicativos) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 8c5ab774..6b4bb56b 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -165,4 +165,6 @@ Включить языки Поиск языков слов + Быстрое удаление + Стирать целые слова, удерживая клавишу Backspace.\n(Не поддерживается в некоторых приложениях) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index d6db88c5..cb310f61 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -168,4 +168,6 @@ Dilleri etkinleştir Diller için arama kelime + Hızlı Silme + Geri tuşunu basılı tutarak tüm kelimeleri silin.\n(Bazı uygulamalarda desteklenmez) diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index a33a2668..e9e06144 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -176,4 +176,6 @@ Увімкнути мови Пошук мов слів + Швидке видалення + Видаляти цілі слова, утримуючи клавішу Backspace.\n(Не підтримується в деяких додатках) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b4330113..c950f751 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -23,6 +23,7 @@ \"%1$s\" added. Add Word + Select a Command About @@ -52,6 +53,8 @@ Automatically start sentences with a capital letter. Automatically Capitalize Every Line Start every line with a capital letter, even it is in the middle of a sentence. + Fast Delete + Erase entire words by holding Backspace.\n(Not supported in some apps) Languages Dark Theme Yes diff --git a/app/src/main/res/xml/prefs_screen_keypad.xml b/app/src/main/res/xml/prefs_screen_keypad.xml index 51964dbd..37c38253 100644 --- a/app/src/main/res/xml/prefs_screen_keypad.xml +++ b/app/src/main/res/xml/prefs_screen_keypad.xml @@ -14,6 +14,14 @@ app:title="@string/pref_haptic_feedback" app:summary="@string/pref_haptic_feedback_summary"/> + + + +