1
0
Fork 0

improved support for phone, decimal and signed integer numeric fields

This commit is contained in:
Dimo Karaivanov 2023-08-28 12:19:17 +03:00
parent 5ece90cd21
commit 81df61b900
6 changed files with 125 additions and 44 deletions

View file

@ -63,8 +63,20 @@ public class TraditionalT9 extends KeyPadHandler {
return settings;
}
public int getInputMode() {
return mInputMode != null ? mInputMode.getId() : InputMode.MODE_UNDEFINED;
public boolean isInputModeNumeric() {
return mInputMode != null && mInputMode.is123();
}
public boolean isNumericModeStrict() {
return mInputMode != null && mInputMode.is123() && inputType.isNumeric() && !inputType.isPhoneNumber();
}
public boolean isNumericModeSigned() {
return mInputMode != null && mInputMode.is123() && inputType.isSignedNumber();
}
public boolean isInputModePhone() {
return mInputMode != null && mInputMode.is123() && inputType.isPhoneNumber();
}
public int getTextCase() {
@ -96,7 +108,7 @@ public class TraditionalT9 extends KeyPadHandler {
private void determineInputMode() {
allowedInputModes = textField.determineInputModes(inputType);
int validModeId = InputModeValidator.validateMode(settings.getInputMode(), allowedInputModes);
mInputMode = InputMode.getInstance(settings, mLanguage, validModeId);
mInputMode = InputMode.getInstance(settings, mLanguage, inputType, validModeId);
}
@ -669,7 +681,7 @@ public class TraditionalT9 extends KeyPadHandler {
if (mInputMode.isPassthrough()) {
return;
} else if (allowedInputModes.size() == 1 && allowedInputModes.contains(InputMode.MODE_123)) {
mInputMode = !mInputMode.is123() ? InputMode.getInstance(settings, mLanguage, InputMode.MODE_123) : mInputMode;
mInputMode = !mInputMode.is123() ? InputMode.getInstance(settings, mLanguage, inputType, InputMode.MODE_123) : mInputMode;
}
// when typing a word or viewing scrolling the suggestions, only change the case
else if (!isSuggestionViewHidden()) {
@ -693,7 +705,7 @@ public class TraditionalT9 extends KeyPadHandler {
mInputMode.nextTextCase();
} else {
int nextModeIndex = (allowedInputModes.indexOf(mInputMode.getId()) + 1) % allowedInputModes.size();
mInputMode = InputMode.getInstance(settings, mLanguage, allowedInputModes.get(nextModeIndex));
mInputMode = InputMode.getInstance(settings, mLanguage, inputType, allowedInputModes.get(nextModeIndex));
mInputMode.setTextFieldCase(textField.determineTextCase(inputType));
mInputMode.determineNextWordTextCase(textField.isThereText(), textField.getTextBeforeCursor());

View file

@ -24,7 +24,7 @@ public class InputType {
* isLimited
* Special or limited input type means the input connection is not rich,
* or it can not process or show things like candidate text, nor retrieve the current text.
*
* <p>
* More info: <a href="https://developer.android.com/reference/android/text/InputType#TYPE_NULL">android docs</a>.
*/
public boolean isLimited() {
@ -36,24 +36,44 @@ 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: <a href="https://github.com/sspanak/tt9/issues/46">in this Github issue</a>
* and <a href="https://github.com/sspanak/tt9/pull/326">the PR about calculators</a>.
*/
public boolean isSpecialNumeric() {
if (field == null) {
return false;
return
isPhoneNumber() && field.packageName.equals("com.android.dialer")
|| isNumeric() && field.packageName.contains("com.android.calculator");
}
int inputType = field.inputType & android.text.InputType.TYPE_MASK_CLASS;
public boolean isPhoneNumber() {
return
inputType == android.text.InputType.TYPE_CLASS_PHONE && field.packageName.equals("com.android.dialer")
|| inputType == android.text.InputType.TYPE_CLASS_NUMBER && field.packageName.contains("com.android.calculator");
field != null
&& (field.inputType & android.text.InputType.TYPE_MASK_CLASS) == android.text.InputType.TYPE_CLASS_PHONE;
}
public boolean isNumeric() {
return
field != null
&& (field.inputType & android.text.InputType.TYPE_MASK_CLASS) == android.text.InputType.TYPE_CLASS_NUMBER;
}
public boolean isDecimal() {
return
isNumeric()
&& (field.inputType & android.text.InputType.TYPE_MASK_FLAGS) == android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL;
}
public boolean isSignedNumber() {
return
isNumeric()
&& (field.inputType & android.text.InputType.TYPE_MASK_FLAGS) == android.text.InputType.TYPE_NUMBER_FLAG_SIGNED;
}

View file

@ -12,7 +12,6 @@ import io.github.sspanak.tt9.preferences.SettingsStore;
abstract public class InputMode {
// typing mode
public static final int MODE_UNDEFINED = -1;
public static final int MODE_PREDICTIVE = 0;
public static final int MODE_ABC = 1;
public static final int MODE_123 = 2;
@ -34,7 +33,7 @@ abstract public class InputMode {
protected final ArrayList<String> suggestions = new ArrayList<>();
public static InputMode getInstance(SettingsStore settings, Language language, int mode) {
public static InputMode getInstance(SettingsStore settings, Language language, InputType inputType, int mode) {
switch (mode) {
case MODE_PREDICTIVE:
return new ModePredictive(settings, language);
@ -45,7 +44,7 @@ abstract public class InputMode {
default:
Logger.w("InputMode", "Defaulting to mode: " + Mode123.class.getName() + " for unknown InputMode: " + mode);
case MODE_123:
return new Mode123();
return new Mode123(inputType);
}
}

View file

@ -3,8 +3,10 @@ package io.github.sspanak.tt9.ime.modes;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import io.github.sspanak.tt9.ime.helpers.InputType;
import io.github.sspanak.tt9.languages.Characters;
public class Mode123 extends ModePassthrough {
@ -18,7 +20,47 @@ public class Mode123 extends ModePassthrough {
private final ArrayList<ArrayList<String>> KEY_CHARACTERS = new ArrayList<>();
public Mode123() {
public Mode123(InputType inputType) {
if (inputType.isPhoneNumber()) {
getPhoneSpecialCharacters();
} else if (inputType.isNumeric()) {
getNumberSpecialCharacters(inputType.isDecimal(), inputType.isSignedNumber());
} else {
getDefaultSpecialCharacters();
}
}
/**
* getPhoneSpecialCharacters
* Special characters for phone number fields, including both characters for conveniently typing a phone number: "()-",
* as well as command characters such as "," = "slight pause" and ";" = "wait" used in Japan and some other countries.
*/
private void getPhoneSpecialCharacters() {
KEY_CHARACTERS.add(new ArrayList<>(Arrays.asList("+", " ")));
KEY_CHARACTERS.add(new ArrayList<>(Arrays.asList("-", "(", ")", ".", ";", ",")));
}
/**
* getNumberSpecialCharacters
* Special characters for all kinds of numeric fields: integer, decimal with +/- included as necessary.
*/
private void getNumberSpecialCharacters(boolean decimal, boolean signed) {
KEY_CHARACTERS.add(signed ? new ArrayList<>(Arrays.asList("-", "+")) : new ArrayList<>());
if (decimal) {
KEY_CHARACTERS.add(new ArrayList<>(Arrays.asList(".", ",")));
}
}
/**
* getDefaultSpecialCharacters
* Special characters for when the user has selected 123 mode in a text field. In this case, we just
* use the default list, but reorder it a bit for convenience.
*/
private void getDefaultSpecialCharacters() {
// 0-key
KEY_CHARACTERS.add(new ArrayList<>(Collections.singletonList("+")));
for (String character : Characters.Special) {
@ -36,10 +78,11 @@ public class Mode123 extends ModePassthrough {
}
}
@Override public boolean onNumber(int number, boolean hold, int repeat) {
reset();
if (hold && number < KEY_CHARACTERS.size()) {
if (hold && number < KEY_CHARACTERS.size() && KEY_CHARACTERS.get(number).size() > 0) {
suggestions.addAll(KEY_CHARACTERS.get(number));
} else {
autoAcceptTimeout = 0;
@ -49,6 +92,7 @@ public class Mode123 extends ModePassthrough {
return true;
}
/**
* shouldIgnoreText
* Since this is a numeric mode, we allow typing only numbers and:

View file

@ -64,8 +64,13 @@ public class SoftNumberKey extends SoftKey {
int number = getNumber(getId());
// 0
if (number == 0) {
if (tt9.getInputMode() == InputMode.MODE_123) {
if (tt9.isNumericModeSigned()) {
return "+/-";
} else if (tt9.isNumericModeStrict()) {
return null;
} else if (tt9.isInputModeNumeric()) {
return "+";
} else {
COMPLEX_LABEL_SUB_TITLE_SIZE = 1;
@ -75,11 +80,11 @@ public class SoftNumberKey extends SoftKey {
// 1
if (number == 1) {
return ",:-)";
return tt9.isNumericModeStrict() ? null : ",:-)";
}
// no other special labels in 123 mode
if (tt9.getInputMode() == InputMode.MODE_123) {
if (tt9.isInputModeNumeric()) {
return null;
}

View file

@ -4,7 +4,6 @@ import android.content.Context;
import android.util.AttributeSet;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.ime.modes.InputMode;
public class SoftPunctuationKey extends SoftKey {
public SoftPunctuationKey(Context context) {
@ -21,37 +20,39 @@ public class SoftPunctuationKey extends SoftKey {
@Override
protected boolean handleRelease() {
if (!validateTT9Handler()) {
return false;
}
int keyId = getId();
if (tt9.getInputMode() == InputMode.MODE_123) {
if (keyId == R.id.soft_key_punctuation_1) return tt9.onText("*");
if (keyId == R.id.soft_key_punctuation_2) return tt9.onText("#");
} else {
if (keyId == R.id.soft_key_punctuation_1) return tt9.onText("!");
if (keyId == R.id.soft_key_punctuation_2) return tt9.onText("?");
}
return true;
return tt9.onText(getKeyChar());
}
@Override
protected String getTitle() {
if (tt9 == null) {
String keyChar = getKeyChar();
switch (keyChar) {
case "":
return "PUNC";
case "*":
return "";
default:
return keyChar;
}
}
private String getKeyChar() {
if (!validateTT9Handler()) {
return "";
}
int keyId = getId();
if (tt9.getInputMode() == InputMode.MODE_123) {
if (keyId == R.id.soft_key_punctuation_1) return "";
if (tt9.isInputModePhone()) {
if (keyId == R.id.soft_key_punctuation_1) return "*";
if (keyId == R.id.soft_key_punctuation_2) return "#";
} else if (tt9.isInputModeNumeric()) {
if (keyId == R.id.soft_key_punctuation_1) return ",";
if (keyId == R.id.soft_key_punctuation_2) return ".";
} else {
if (keyId == R.id.soft_key_punctuation_1) return "!";
if (keyId == R.id.soft_key_punctuation_2) return "?";
}
return "PUNC";
return "";
}
}