restructured the hacks code; added a hack for detecting the LG X100S dialer correctly
This commit is contained in:
parent
480e541527
commit
464321ec3d
9 changed files with 92 additions and 89 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
package io.github.sspanak.tt9.hacks;
|
package io.github.sspanak.tt9.hacks;
|
||||||
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.inputmethod.EditorInfo;
|
|
||||||
import android.view.inputmethod.InputConnection;
|
import android.view.inputmethod.InputConnection;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
@ -11,30 +10,26 @@ import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
|
|
||||||
public class AppHacks {
|
public class AppHacks {
|
||||||
private final ConnectedAppInfo appInfo;
|
|
||||||
private final InputConnection inputConnection;
|
private final InputConnection inputConnection;
|
||||||
|
private final InputType inputType;
|
||||||
private final SettingsStore settings;
|
private final SettingsStore settings;
|
||||||
private final TextField textField;
|
private final TextField textField;
|
||||||
|
|
||||||
|
|
||||||
public AppHacks(SettingsStore settings, InputConnection inputConnection, EditorInfo inputField, TextField textField) {
|
public AppHacks(SettingsStore settings, InputConnection inputConnection, InputType inputType, TextField textField) {
|
||||||
this.inputConnection = inputConnection;
|
this.inputConnection = inputConnection;
|
||||||
|
this.inputType = inputType;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.textField = textField;
|
this.textField = textField;
|
||||||
appInfo = new ConnectedAppInfo(inputConnection, inputField);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ConnectedAppInfo getAppInfo() {
|
|
||||||
return appInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* setComposingTextWithHighlightedStem
|
* setComposingTextWithHighlightedStem
|
||||||
* A compatibility function for text fields that do not support SpannableString. Effectively disables highlighting.
|
* A compatibility function for text fields that do not support SpannableString. Effectively disables highlighting.
|
||||||
*/
|
*/
|
||||||
public void setComposingTextWithHighlightedStem(@NonNull String word, InputMode inputMode) {
|
public void setComposingTextWithHighlightedStem(@NonNull String word, InputMode inputMode) {
|
||||||
if (appInfo.isKindleInvertedTextField()) {
|
if (inputType.isKindleInvertedTextField()) {
|
||||||
textField.setComposingText(word);
|
textField.setComposingText(word);
|
||||||
} else {
|
} else {
|
||||||
textField.setComposingTextWithHighlightedStem(word, inputMode);
|
textField.setComposingTextWithHighlightedStem(word, inputMode);
|
||||||
|
|
@ -48,9 +43,9 @@ public class AppHacks {
|
||||||
* returned, you must not attempt to delete text. This function has already done everything necessary.
|
* returned, you must not attempt to delete text. This function has already done everything necessary.
|
||||||
*/
|
*/
|
||||||
public boolean onBackspace(InputMode inputMode) {
|
public boolean onBackspace(InputMode inputMode) {
|
||||||
if (appInfo.isKindleInvertedTextField()) {
|
if (inputType.isKindleInvertedTextField()) {
|
||||||
inputMode.clearWordStem();
|
inputMode.clearWordStem();
|
||||||
} else if (appInfo.isTermux()) {
|
} else if (inputType.isTermux()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,7 +60,7 @@ public class AppHacks {
|
||||||
* Returns "true" if the action was handled, "false" otherwise.
|
* Returns "true" if the action was handled, "false" otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean onAction(int action) {
|
public boolean onAction(int action) {
|
||||||
if (appInfo.isSonimSearchField(action)) {
|
if (inputType.isSonimSearchField(action)) {
|
||||||
return sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);
|
return sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,11 +75,11 @@ public class AppHacks {
|
||||||
* it does nothing and return "false", signaling the system we have ignored the key press.
|
* it does nothing and return "false", signaling the system we have ignored the key press.
|
||||||
*/
|
*/
|
||||||
public boolean onEnter() {
|
public boolean onEnter() {
|
||||||
if (settings.getFbMessengerHack() && appInfo.isMessenger()) {
|
if (settings.getFbMessengerHack() && inputType.isMessenger()) {
|
||||||
return onEnterFbMessenger();
|
return onEnterFbMessenger();
|
||||||
} else if (settings.getGoogleChatHack() && appInfo.isGoogleChat()) {
|
} else if (settings.getGoogleChatHack() && inputType.isGoogleChat()) {
|
||||||
return onEnterGoogleChat();
|
return onEnterGoogleChat();
|
||||||
} else if (appInfo.isTermux() || appInfo.isMultilineTextInNonSystemApp()) {
|
} else if (inputType.isTermux() || inputType.isMultilineTextInNonSystemApp()) {
|
||||||
// Termux supports only ENTER, so we convert DPAD_CENTER for it.
|
// Termux supports only ENTER, so we convert DPAD_CENTER for it.
|
||||||
// Any extra installed apps are likely not designed for hardware keypads, so again,
|
// Any extra installed apps are likely not designed for hardware keypads, so again,
|
||||||
// we don't want to send DPAD_CENTER to them.
|
// we don't want to send DPAD_CENTER to them.
|
||||||
|
|
|
||||||
|
|
@ -3,20 +3,23 @@ package io.github.sspanak.tt9.hacks;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.view.inputmethod.InputConnection;
|
import android.view.inputmethod.InputConnection;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.ime.helpers.StandardInputType;
|
||||||
|
|
||||||
public class ConnectedAppInfo {
|
public class InputType extends StandardInputType {
|
||||||
final EditorInfo editorInfo;
|
public InputType(InputConnection inputConnection, EditorInfo inputField){
|
||||||
final InputType inputType;
|
super(inputConnection, inputField);
|
||||||
|
|
||||||
|
|
||||||
ConnectedAppInfo(InputConnection inputConnection, EditorInfo inputField) {
|
|
||||||
this.editorInfo = inputField;
|
|
||||||
this.inputType = new InputType(inputConnection, inputField);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
boolean isGoogleChat() {
|
||||||
|
return isAppField(
|
||||||
|
"com.google.android.apps.dynamite",
|
||||||
|
EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
* isKindleInvertedTextField
|
* isKindleInvertedTextField
|
||||||
* When sharing a document to the Amazon Kindle app. It displays a screen where one could edit the title and the author of the
|
* When sharing a document to the Amazon Kindle app. It displays a screen where one could edit the title and the author of the
|
||||||
* document. These two fields do not support SpannableString, which is used for suggestion highlighting. When they receive one
|
* document. These two fields do not support SpannableString, which is used for suggestion highlighting. When they receive one
|
||||||
|
|
@ -30,29 +33,22 @@ public class ConnectedAppInfo {
|
||||||
return
|
return
|
||||||
isAppField("com.amazon.kindle", EditorInfo.TYPE_CLASS_TEXT)
|
isAppField("com.amazon.kindle", EditorInfo.TYPE_CLASS_TEXT)
|
||||||
&& (
|
&& (
|
||||||
editorInfo.imeOptions == titleImeOptions
|
field.imeOptions == titleImeOptions
|
||||||
|| editorInfo.imeOptions == titleAlternativeImeOptions
|
|| field.imeOptions == titleAlternativeImeOptions
|
||||||
|| editorInfo.imeOptions == authorImeOptions
|
|| field.imeOptions == authorImeOptions
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
public boolean isLgX100SDialer() {
|
||||||
* isTermux
|
int imeOptions = EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_ENTER_ACTION | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS;
|
||||||
* Termux is a terminal emulator and it naturally has a text input, but it incorrectly introduces itself as having a NULL input,
|
return
|
||||||
* instead of a plain text input. However NULL inputs are usually, buttons and dropdown menus, which indeed can not read text
|
DeviceInfo.isLgX100S()
|
||||||
* and are ignored by TT9 by default. In order not to ignore Termux, we need this.
|
&& isAppField("com.android.contacts", EditorInfo.TYPE_CLASS_PHONE)
|
||||||
*/
|
&& field.imeOptions == imeOptions;
|
||||||
public boolean isTermux() {
|
|
||||||
return isAppField("com.termux", EditorInfo.TYPE_NULL) && editorInfo.fieldId > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* isMessenger
|
|
||||||
* Facebook Messenger has flaky support for sending messages. To fix that, we detect the chat input field and send the appropriate
|
|
||||||
* key codes to it. See "onFbMessengerEnter()" for info how the hack works.
|
|
||||||
*/
|
|
||||||
boolean isMessenger() {
|
boolean isMessenger() {
|
||||||
return isAppField(
|
return isAppField(
|
||||||
"com.facebook.orca",
|
"com.facebook.orca",
|
||||||
|
|
@ -61,16 +57,12 @@ public class ConnectedAppInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Third-party apps are usually designed for a touch screen, so the least we can do is convert
|
||||||
|
* DPAD_CENTER to ENTER for typing new lines, regardless of the implementation of the OK key.
|
||||||
|
*/
|
||||||
boolean isMultilineTextInNonSystemApp() {
|
boolean isMultilineTextInNonSystemApp() {
|
||||||
return editorInfo != null && !editorInfo.packageName.contains("android") && inputType.isMultilineText();
|
return field != null && !field.packageName.contains("android") && isMultilineText();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
boolean isGoogleChat() {
|
|
||||||
return isAppField(
|
|
||||||
"com.google.android.apps.dynamite",
|
|
||||||
EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -83,24 +75,57 @@ public class ConnectedAppInfo {
|
||||||
boolean isSonimSearchField(int action) {
|
boolean isSonimSearchField(int action) {
|
||||||
return
|
return
|
||||||
DeviceInfo.isSonim() &&
|
DeviceInfo.isSonim() &&
|
||||||
editorInfo != null && (editorInfo.packageName.startsWith("com.android") || editorInfo.packageName.startsWith("com.sonim"))
|
field != null && (field.packageName.startsWith("com.android") || field.packageName.startsWith("com.sonim"))
|
||||||
&& (editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION) == action
|
&& (field.imeOptions & EditorInfo.IME_MASK_ACTION) == action
|
||||||
&& (
|
&& (
|
||||||
inputType.isText()
|
isText()
|
||||||
// in some apps, they forgot to set the TEXT type, but fortunately, they did set the NO_SUGGESTIONS flag.
|
// in some apps, they forgot to set the TEXT type, but fortunately, they did set the NO_SUGGESTIONS flag.
|
||||||
|| ((editorInfo.inputType & EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS) == EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS)
|
|| ((field.inputType & EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS) == EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isTermux
|
||||||
|
* Termux is a terminal emulator and it naturally has a text input, but it incorrectly introduces itself as having a NULL input,
|
||||||
|
* instead of a plain text input. However NULL inputs are usually, buttons and dropdown menus, which indeed can not read text
|
||||||
|
* and are ignored by TT9 by default. In order not to ignore Termux, we need this.
|
||||||
|
*/
|
||||||
|
public boolean isTermux() {
|
||||||
|
return isAppField("com.termux", EditorInfo.TYPE_NULL) && field.fieldId > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isSpecialNumeric
|
||||||
|
* Calculator and Dialer fields seem to take care of numbers and backspace on their own,
|
||||||
|
* so we need to be aware of them.
|
||||||
|
* <p>
|
||||||
|
* NOTE: A Dialer field is not the same as Phone field. Dialer is where you
|
||||||
|
* actually dial and call a phone number. While the Phone field is a text
|
||||||
|
* field in any app or a webpage, intended for typing phone numbers.
|
||||||
|
* <p>
|
||||||
|
* More info (chronological order of bug fixing):
|
||||||
|
* <a href="https://github.com/sspanak/tt9/issues/46">the initial GitHub issue about Qin F21 Pro+</a>
|
||||||
|
* <a href="https://github.com/sspanak/tt9/pull/326">the PR about calculators</a>
|
||||||
|
* <a href="https://github.com/sspanak/tt9/issues/300">Dialer not detected correctly on LG X100S</a>
|
||||||
|
*/
|
||||||
|
protected boolean isSpecialNumeric() {
|
||||||
|
return
|
||||||
|
field.packageName.contains("com.android.calculator") // there is "calculator2", hence the contains()
|
||||||
|
|| field.packageName.equals("com.android.dialer")
|
||||||
|
|| isLgX100SDialer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* isAppField
|
* isAppField
|
||||||
* Detects a particular input field of a particular application.
|
* Detects a particular input field of a particular application.
|
||||||
*/
|
*/
|
||||||
boolean isAppField(String appPackageName, int fieldSpec) {
|
boolean isAppField(String appPackageName, int fieldSpec) {
|
||||||
return
|
return
|
||||||
editorInfo != null
|
field != null
|
||||||
&& ((editorInfo.inputType & fieldSpec) == fieldSpec)
|
&& ((field.inputType & fieldSpec) == fieldSpec)
|
||||||
&& editorInfo.packageName.equals(appPackageName);
|
&& field.packageName.equals(appPackageName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,8 +12,8 @@ import java.util.ArrayList;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.DictionaryLoader;
|
import io.github.sspanak.tt9.db.DictionaryLoader;
|
||||||
import io.github.sspanak.tt9.hacks.AppHacks;
|
import io.github.sspanak.tt9.hacks.AppHacks;
|
||||||
|
import io.github.sspanak.tt9.hacks.InputType;
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputModeValidator;
|
import io.github.sspanak.tt9.ime.helpers.InputModeValidator;
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
|
||||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.ime.modes.ModePredictive;
|
import io.github.sspanak.tt9.ime.modes.ModePredictive;
|
||||||
|
|
@ -80,7 +80,7 @@ public abstract class TypingHandler extends KeyPadHandler {
|
||||||
textField = new TextField(currentInputConnection, field);
|
textField = new TextField(currentInputConnection, field);
|
||||||
|
|
||||||
// changing the TextField and notifying all interested classes is an atomic operation
|
// changing the TextField and notifying all interested classes is an atomic operation
|
||||||
appHacks = new AppHacks(settings, connection, field, textField);
|
appHacks = new AppHacks(settings, connection, inputType, textField);
|
||||||
suggestionOps.setTextField(textField);
|
suggestionOps.setTextField(textField);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,7 +229,7 @@ public abstract class TypingHandler extends KeyPadHandler {
|
||||||
* We do not want to handle any of these, hence we pass through all input to the system.
|
* We do not want to handle any of these, hence we pass through all input to the system.
|
||||||
*/
|
*/
|
||||||
protected int getInputModeId() {
|
protected int getInputModeId() {
|
||||||
if (!inputType.isValid() || (inputType.isLimited() && !appHacks.getAppInfo().isTermux())) {
|
if (!inputType.isValid() || (inputType.isLimited() && !inputType.isTermux())) {
|
||||||
return InputMode.MODE_PASSTHROUGH;
|
return InputMode.MODE_PASSTHROUGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,14 @@ import java.util.ArrayList;
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
|
|
||||||
|
|
||||||
public class InputType {
|
abstract public class StandardInputType {
|
||||||
private static final int TYPE_MULTILINE_TEXT = EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
|
private static final int TYPE_MULTILINE_TEXT = EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
|
||||||
|
|
||||||
private final InputConnection connection;
|
protected final InputConnection connection;
|
||||||
private final EditorInfo field;
|
protected final EditorInfo field;
|
||||||
|
|
||||||
|
|
||||||
public InputType(InputConnection inputConnection, EditorInfo inputField) {
|
protected StandardInputType(InputConnection inputConnection, EditorInfo inputField) {
|
||||||
connection = inputConnection;
|
connection = inputConnection;
|
||||||
field = inputField;
|
field = inputField;
|
||||||
}
|
}
|
||||||
|
|
@ -38,27 +38,6 @@ public class InputType {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* isSpecialNumeric
|
|
||||||
* Calculator and Dialer fields seem to take care of numbers and backspace on their own,
|
|
||||||
* so we need to be aware of them.
|
|
||||||
* <p>
|
|
||||||
* NOTE: A Dialer field is not the same as Phone field. Dialer is where you
|
|
||||||
* actually dial and call a phone number. While the Phone field is a text
|
|
||||||
* field in any app or a webpage, intended for typing phone numbers.
|
|
||||||
* <p>
|
|
||||||
* More info (chronological order of bugfixing):
|
|
||||||
* <a href="https://github.com/sspanak/tt9/issues/46">in this Github issue</a>
|
|
||||||
* <a href="https://github.com/sspanak/tt9/pull/326">the PR about calculators</a>
|
|
||||||
* <a href="https://github.com/sspanak/tt9/issues/300">Dialer not detected correctly on LG X100S</a>
|
|
||||||
*/
|
|
||||||
private boolean isSpecialNumeric() {
|
|
||||||
return
|
|
||||||
field.packageName.contains("com.android.calculator") // there is "calculator2", hence the contains()
|
|
||||||
|| field.packageName.equals("com.android.dialer");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean isPhoneNumber() {
|
public boolean isPhoneNumber() {
|
||||||
return
|
return
|
||||||
field != null
|
field != null
|
||||||
|
|
@ -85,6 +64,9 @@ public class InputType {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
abstract protected boolean isSpecialNumeric();
|
||||||
|
|
||||||
|
|
||||||
public boolean isEmail() {
|
public boolean isEmail() {
|
||||||
if (field == null) {
|
if (field == null) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -10,6 +10,7 @@ import android.view.inputmethod.InputConnection;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.hacks.InputType;
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.LanguageKind;
|
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.hacks.InputType;
|
||||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.NaturalLanguage;
|
import io.github.sspanak.tt9.languages.NaturalLanguage;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.hacks.InputType;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.NaturalLanguage;
|
import io.github.sspanak.tt9.languages.NaturalLanguage;
|
||||||
import io.github.sspanak.tt9.util.Characters;
|
import io.github.sspanak.tt9.util.Characters;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import androidx.annotation.NonNull;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.db.WordStoreAsync;
|
import io.github.sspanak.tt9.db.WordStoreAsync;
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.hacks.InputType;
|
||||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||||
import io.github.sspanak.tt9.ime.modes.helpers.AutoSpace;
|
import io.github.sspanak.tt9.ime.modes.helpers.AutoSpace;
|
||||||
import io.github.sspanak.tt9.ime.modes.helpers.AutoTextCase;
|
import io.github.sspanak.tt9.ime.modes.helpers.AutoTextCase;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package io.github.sspanak.tt9.ime.modes.helpers;
|
package io.github.sspanak.tt9.ime.modes.helpers;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.hacks.InputType;
|
||||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
import io.github.sspanak.tt9.util.Text;
|
import io.github.sspanak.tt9.util.Text;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue