1
0
Fork 0

multi-press protection hack

This commit is contained in:
sspanak 2024-02-11 19:51:17 +02:00 committed by Dimo Karaivanov
parent 6b95c6b9d1
commit 81d71abe39
18 changed files with 158 additions and 20 deletions

View file

@ -6,6 +6,8 @@ import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import java.util.HashMap;
import io.github.sspanak.tt9.Logger;
import io.github.sspanak.tt9.ime.helpers.Key;
import io.github.sspanak.tt9.preferences.SettingsStore;
@ -14,6 +16,9 @@ import io.github.sspanak.tt9.preferences.SettingsStore;
abstract class KeyPadHandler extends InputMethodService {
protected SettingsStore settings;
// debounce handling
private final HashMap<Integer, Long> lastKeyTime = new HashMap<>();
// temporal key handling
private boolean isBackspaceHandled = false;
@ -112,6 +117,10 @@ abstract class KeyPadHandler extends InputMethodService {
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (debounceKey(keyCode, event)) {
return true;
}
if (shouldBeOff()) {
return false;
}
@ -187,6 +196,10 @@ abstract class KeyPadHandler extends InputMethodService {
*/
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (debounceKey(keyCode, event)) {
return true;
}
if (shouldBeOff()) {
return false;
}
@ -273,6 +286,26 @@ abstract class KeyPadHandler extends InputMethodService {
}
private boolean debounceKey(int keyCode, KeyEvent event) {
if (settings.getKeyPadDebounceTime() <= 0 || event.isLongPress()) {
return false;
}
long now = System.currentTimeMillis();
Long lastTime = lastKeyTime.get(keyCode);
if (lastTime != null && now - lastTime < settings.getKeyPadDebounceTime()) {
return true;
}
if (event.getAction() == KeyEvent.ACTION_UP) {
lastKeyTime.put(keyCode, now);
}
return false;
}
// hardware key handlers
abstract protected boolean onBack();
abstract public boolean onBackspace();

View file

@ -256,7 +256,7 @@ public class SettingsStore {
/************* typing settings *************/
public int getAbcAutoAcceptTimeout() { return prefs.getBoolean("abc_auto_accept", true) ? 800 : -1; }
public int getAbcAutoAcceptTimeout() { return prefs.getBoolean("abc_auto_accept", true) ? 800 + getKeyPadDebounceTime() : -1; }
public boolean getAutoSpace() { return prefs.getBoolean("auto_space", true); }
public boolean getAutoTextCase() { return prefs.getBoolean("auto_text_case", true); }
public String getDoubleZeroChar() {
@ -275,7 +275,6 @@ public class SettingsStore {
public final static int DICTIONARY_IMPORT_BATCH_SIZE = 5000; // words
public final static int DICTIONARY_IMPORT_PROGRESS_UPDATE_TIME = 250; // ms
public final static int DICTIONARY_MISSING_WARNING_INTERVAL = 30000; // ms
public final static int PREFERENCES_CLICK_DEBOUNCE_TIME = 250; // ms
public final static byte SLOW_QUERY_TIME = 50; // ms
public final static int SOFT_KEY_REPEAT_DELAY = 40; // ms
public final static float SOFT_KEY_COMPLEX_LABEL_TITLE_SIZE = 0.55f;
@ -304,4 +303,20 @@ public class SettingsStore {
public boolean getGoogleChatHack() {
return prefs.getBoolean("pref_hack_google_chat", false);
}
/**
* Protection against faulty devices, that sometimes send two (or more) click events
* per a single key press, which absolutely undesirable side effects.
* There were reports about this on <a href="https://github.com/sspanak/tt9/issues/117">Kyocera KYF31</a>
* and on <a href="https://github.com/sspanak/tt9/issues/399">CAT S22</a>.
*/
public final static int PREFERENCES_CLICK_DEBOUNCE_TIME = 250; // ms
public int getKeyPadDebounceTime() {
try {
return Integer.parseInt(prefs.getString("pref_key_pad_debounce_time", "0"));
} catch (NumberFormatException e) {
return 0;
}
}
}

View file

@ -57,16 +57,6 @@ abstract public class ItemClickable {
}
/**
* debounceClick
* Protection against faulty devices, that sometimes send two (or more) click events
* per a single key press.
*
* My smashed Qin F21 Pro+ occasionally does this, if I press the keys hard.
* There were reports the same happens on Kyocera KYF31, causing absolutely undesirable side effects.
* See: <a href="https://github.com/sspanak/tt9/issues/117">...</a>
*/
protected boolean debounceClick(Preference p) {
long now = System.currentTimeMillis();
if (now - lastClickTime < SettingsStore.PREFERENCES_CLICK_DEBOUNCE_TIME) {

View file

@ -33,6 +33,20 @@ public class ItemDropDown {
item.setEntries(this.values.values().toArray(new CharSequence[0]));
}
public void disable() {
if (item != null) {
item.setEnabled(false);
item.setOnPreferenceChangeListener(null);
}
}
public void enable() {
if (item != null) {
item.setEnabled(true);
enableClickHandler();
}
}
public ItemDropDown enableClickHandler() {
if (item == null) {
Logger.w("SectionKeymap.populateItem", "Cannot set a click listener a NULL item. Ignoring.");
@ -63,7 +77,7 @@ public class ItemDropDown {
public void preview() {
try {
setPreview(values.get(Integer.parseInt(item.getValue())));
} catch (NumberFormatException e) {
} catch (Exception e) {
setPreview("");
}
}

View file

@ -0,0 +1,33 @@
package io.github.sspanak.tt9.preferences.items;
import android.content.Context;
import androidx.preference.DropDownPreference;
import java.util.LinkedHashMap;
import io.github.sspanak.tt9.R;
public class ItemKeyPadDebounceTime extends ItemDropDown {
public static final String NAME = "pref_key_pad_debounce_time";
private final Context context;
public ItemKeyPadDebounceTime(Context context, DropDownPreference item) {
super(item);
this.context = context;
}
public ItemDropDown populate() {
LinkedHashMap<Integer, String> dropDownOptions = new LinkedHashMap<>();
dropDownOptions.put(0, context.getString(R.string.pref_hack_key_pad_debounce_off));
int[] values = new int[] { 33, 50, 100, 150, 250, 350 };
for (int value : values) {
dropDownOptions.put(value, value + " ms");
}
super.populate(dropDownOptions);
return this;
}
}

View file

@ -5,6 +5,7 @@ import androidx.preference.Preference;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.ime.helpers.SystemSettings;
import io.github.sspanak.tt9.preferences.PreferencesActivity;
import io.github.sspanak.tt9.preferences.items.ItemKeyPadDebounceTime;
import io.github.sspanak.tt9.preferences.items.ItemSelectGlobalKeyboard;
import io.github.sspanak.tt9.preferences.items.ItemSetDefaultGlobalKeyboard;
@ -17,18 +18,18 @@ public class SetupScreen extends BaseScreenFragment {
@Override
public void onCreate() {
createKeyboardSection();
boolean isTT9On = SystemSettings.isTT9Enabled(activity);
createKeyboardSection(isTT9On);
createHacksSection(isTT9On);
}
@Override
public void onResume() {
super.onResume();
createKeyboardSection();
onCreate();
}
private void createKeyboardSection() {
boolean isTT9On = SystemSettings.isTT9Enabled(activity);
private void createKeyboardSection(boolean isTT9On) {
Preference statusItem = findPreference("global_tt9_status");
if (statusItem != null) {
statusItem.setSummary(
@ -43,4 +44,29 @@ public class SetupScreen extends BaseScreenFragment {
new ItemSetDefaultGlobalKeyboard(defaultKeyboardItem, activity).enableClickHandler();
}
}
private void createHacksSection(boolean isTT9On) {
Preference altScrolling = findPreference("pref_alternative_suggestion_scrolling");
if (altScrolling != null) {
altScrolling.setEnabled(isTT9On);
}
Preference hackGoogleChat = findPreference("pref_hack_google_chat");
if (hackGoogleChat != null) {
hackGoogleChat.setEnabled(isTT9On);
}
Preference hackFBMessenger = findPreference("pref_hack_fb_messenger");
if (hackFBMessenger != null) {
hackFBMessenger.setEnabled(isTT9On);
}
ItemKeyPadDebounceTime item = new ItemKeyPadDebounceTime(activity, findPreference(ItemKeyPadDebounceTime.NAME));
item.populate().preview();
if (isTT9On) {
item.enable();
} else {
item.disable();
}
}
}

View file

@ -82,4 +82,6 @@
<string name="pref_dark_theme_no">Не</string>
<string name="pref_dark_theme_auto">Автоматично</string>
<string name="add_word_confirm">Да се добави ли „%1$s“ към %2$s?</string>
<string name="pref_hack_key_pad_debounce_time">Защита от многократно натискане</string>
<string name="pref_hack_key_pad_debounce_off">Изключена</string>
</resources>

View file

@ -34,4 +34,6 @@
<string name="donate_summary">Wenn Ihnen %1$s gefällt, könnten Sie die Entwicklung auf %2$s unterstützen.</string>
<string name="pref_hack_fb_messenger">Mit \"OK\" in Facebook Messenger senden</string>
<string name="pref_hack_google_chat">Nachrichten mit \"OK\" in Google Chat senden</string>
<string name="pref_hack_key_pad_debounce_time">Mehrfacher Pressschutz</string>
<string name="pref_hack_key_pad_debounce_off">Aus</string>
</resources>

View file

@ -78,4 +78,6 @@
<string name="donate_summary">Si te gusta %1$s, podrías apoyar su desarrollo en: %2$s.</string>
<string name="pref_hack_fb_messenger">Enviar con «OK» en Facebook Messenger</string>
<string name="pref_hack_google_chat">Enviar mensajes con «OK» en Google Chat</string>
<string name="pref_hack_key_pad_debounce_time">Protección con múltiples clics</string>
<string name="pref_hack_key_pad_debounce_off">Apagado</string>
</resources>

View file

@ -76,4 +76,6 @@
<string name="add_word_confirm">Ajouter mot « %1$s » à %2$s?</string>
<string name="donate_title">Donner</string>
<string name="donate_summary">Si vous aimez %1$s vous pouvez soutenir son développement à : %2$s</string>
<string name="pref_hack_key_pad_debounce_time">Protection multi-presse</string>
<string name="pref_hack_key_pad_debounce_off">Désactivée</string>
</resources>

View file

@ -43,5 +43,7 @@
<string name="donate_summary">Se ti piace %1$s, potresti supportarne lo sviluppo su: %2$s.</string>
<string name="pref_hack_fb_messenger">Inviare con \"OK\" su Facebook Messenger</string>
<string name="pref_hack_google_chat">Inviare messaggi con \"OK\" su Google Chat</string>
<string name="pref_hack_key_pad_debounce_time">Protezione multi-pressione</string>
<string name="pref_hack_key_pad_debounce_off">Spento</string>
</resources>

View file

@ -71,4 +71,6 @@
<string name="donate_summary">אם אתה אוהב את %1$s, תוכל לתמוך בפיתוח שלו בכתובת: %2$s</string>
<string name="pref_hack_fb_messenger">שלח עם \"OK\" ב-Facebook Messenger.</string>
<string name="pref_hack_google_chat">שלח הודעות עם \"OK\" ב-Google Chat</string>
<string name="pref_hack_key_pad_debounce_time">הגנה מרובה לחיצות</string>
<string name="pref_hack_key_pad_debounce_off">כבוי</string>
</resources>

View file

@ -34,4 +34,6 @@
<string name="donate_summary">Als je %1$s leuk vindt, zou je de ontwikkeling kunnen ondersteunen op: %2$s.</string>
<string name="pref_hack_fb_messenger">Verstuur met \"OK\" in Facebook Messenger</string>
<string name="pref_hack_google_chat">Stuur berichten met \"OK\" in Google Chat</string>
<string name="pref_hack_key_pad_debounce_time">Bescherming tegen meervoudig persen</string>
<string name="pref_hack_key_pad_debounce_off">Uit</string>
</resources>

View file

@ -67,4 +67,6 @@
<string name="donate_summary">Se você gosta de %1$s, você poderia apoiar o seu desenvolvimento em: %2$s.</string>
<string name="pref_hack_fb_messenger">Enviar com \"OK\" no Facebook Messenger</string>
<string name="pref_hack_google_chat">Enviar mensagens com \"OK\" no Google Chat</string>
<string name="pref_hack_key_pad_debounce_time">Proteção multiclique</string>
<string name="pref_hack_key_pad_debounce_off">Desligado</string>
</resources>

View file

@ -82,4 +82,6 @@
<string name="donate_title">Поддержать</string>
<string name="donate_summary">Если вам нравится %1$s, вы можете поддержать его разработку по: %2$s.</string>
<string name="pref_hack_google_chat">Отправка сообщения с «ОК» в Google Chat</string>
<string name="pref_hack_key_pad_debounce_time">Защита от многократного нажатия</string>
<string name="pref_hack_key_pad_debounce_off">Выключена</string>
</resources>

View file

@ -82,4 +82,6 @@
<string name="donate_title">Підтримуйте</string>
<string name="donate_summary">Якщо вам подобається %1$s, ви можете підтримати його розробку за: %2$s.</string>
<string name="pref_hack_google_chat">Надсилати повідомлення з «ОК» до Google Chat</string>
<string name="pref_hack_key_pad_debounce_time">Захист від багаторазового натискання</string>
<string name="pref_hack_key_pad_debounce_off">Вимкнено</string>
</resources>

View file

@ -47,6 +47,8 @@
<string name="pref_double_zero_char">Character for Double 0-key Press</string>
<string name="pref_hack_google_chat">Send messages with \"OK\" in Google Chat</string>
<string name="pref_hack_fb_messenger">Send with \"OK\" in Facebook Messenger</string>
<string name="pref_hack_key_pad_debounce_time">Multi-Press Protection</string>
<string name="pref_hack_key_pad_debounce_off">Off</string>
<string name="pref_show_soft_function_keys">Show On-Screen Keys</string>
<string name="pref_show_soft_numpad">Show On-Screen Numpad</string>
<string name="pref_show_soft_numpad_summary" translatable="false">(BETA)</string>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
app:layout="@layout/pref_text"
app:orderingFromXml="true">
<Preference
@ -37,5 +36,11 @@
app:layout="@layout/pref_switch"
app:title="@string/pref_hack_fb_messenger"/>
<DropDownPreference
app:iconSpaceReserved="false"
app:key="pref_key_pad_debounce_time"
app:layout="@layout/pref_dropdown"
app:title="@string/pref_hack_key_pad_debounce_time" />
</PreferenceCategory>
</PreferenceScreen>