diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModePredictive.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModePredictive.java index 38cd09a2..edce8f44 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModePredictive.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModePredictive.java @@ -60,18 +60,13 @@ public class ModePredictive extends InputMode { public boolean onBackspace() { isCursorDirectionForward = false; - if (digitSequence.length() < 1) { + if (digitSequence.isEmpty()) { clearWordStem(); return false; } - if (digitSequence.startsWith(EmojiLanguage.EMOJI_SEQUENCE) && specialCharSelectedGroup > 0) { - specialCharSelectedGroup -= 2; - return true; - } - digitSequence = digitSequence.substring(0, digitSequence.length() - 1); - if (digitSequence.length() == 0) { + if (digitSequence.isEmpty()) { clearWordStem(); } else if (stem.length() > digitSequence.length()) { stem = stem.substring(0, digitSequence.length()); @@ -93,16 +88,12 @@ public class ModePredictive extends InputMode { suggestions.add(language.getKeyNumber(number)); } else { super.reset(); - digitSequence += number; + digitSequence = EmojiLanguage.validateEmojiSequence(digitSequence, number); disablePredictions = false; if (digitSequence.equals(Language.PREFERRED_CHAR_SEQUENCE)) { autoAcceptTimeout = 0; } - - // custom emoji are longest 1-key sequence, so do not allow typing any longer than that, - // to prevent side effects - digitSequence = digitSequence.startsWith(EmojiLanguage.CUSTOM_EMOJI_SEQUENCE) ? EmojiLanguage.CUSTOM_EMOJI_SEQUENCE : digitSequence; } return true; @@ -237,7 +228,7 @@ public class ModePredictive extends InputMode { return; } - Language searchLanguage = digitSequence.startsWith(EmojiLanguage.CUSTOM_EMOJI_SEQUENCE) ? new EmojiLanguage() : language; + Language searchLanguage = digitSequence.equals(EmojiLanguage.CUSTOM_EMOJI_SEQUENCE) ? new EmojiLanguage() : language; onSuggestionsUpdated = onLoad; predictions @@ -261,8 +252,9 @@ public class ModePredictive extends InputMode { super.nextSpecialCharacters(); onLoad.run(); return true; - } else if (digitSequence.equals(EmojiLanguage.EMOJI_SEQUENCE)) { - nextSpecialCharacters(new EmojiLanguage()); + } else if (!digitSequence.equals(EmojiLanguage.CUSTOM_EMOJI_SEQUENCE) && digitSequence.startsWith(EmojiLanguage.EMOJI_SEQUENCE)) { + suggestions.clear(); + suggestions.addAll(new EmojiLanguage().getKeyCharacters(digitSequence.charAt(0) - '0', digitSequence.length() - 2)); onLoad.run(); return true; } else if (digitSequence.startsWith(Language.PREFERRED_CHAR_SEQUENCE)) { @@ -282,7 +274,7 @@ public class ModePredictive extends InputMode { */ private void getPredictions() { // in case the user hasn't added any custom emoji, do not allow advancing to the empty character group - if (predictions.getList().isEmpty() && digitSequence.equals(EmojiLanguage.CUSTOM_EMOJI_SEQUENCE)) { + if (predictions.getList().isEmpty() && digitSequence.startsWith(EmojiLanguage.EMOJI_SEQUENCE)) { digitSequence = EmojiLanguage.EMOJI_SEQUENCE; return; } @@ -348,9 +340,7 @@ public class ModePredictive extends InputMode { @Override protected boolean nextSpecialCharacters() { - return - (digitSequence.equals(EmojiLanguage.EMOJI_SEQUENCE) && super.nextSpecialCharacters(new EmojiLanguage())) - || (digitSequence.equals(Language.SPECIAL_CHARS_KEY) && super.nextSpecialCharacters()); + return digitSequence.equals(Language.SPECIAL_CHARS_KEY) && super.nextSpecialCharacters(); } @Override @@ -405,6 +395,7 @@ public class ModePredictive extends InputMode { !digitSequence.isEmpty() && predictions.noDbWords() && digitSequence.contains(Language.PUNCTUATION_KEY) + && !digitSequence.startsWith(EmojiLanguage.EMOJI_SEQUENCE) && Text.containsOtherThan1(digitSequence); } diff --git a/app/src/main/java/io/github/sspanak/tt9/languages/Characters.java b/app/src/main/java/io/github/sspanak/tt9/languages/Characters.java index 46686f81..41d10fc3 100644 --- a/app/src/main/java/io/github/sspanak/tt9/languages/Characters.java +++ b/app/src/main/java/io/github/sspanak/tt9/languages/Characters.java @@ -85,6 +85,10 @@ public class Characters { } } - return availableEmoji.size() > 0 ? availableEmoji : new ArrayList<>(TextEmoticons); + return availableEmoji.isEmpty() ? new ArrayList<>(TextEmoticons) : availableEmoji; + } + + public static int getMaxEmojiLevel() { + return Emoji.size(); } } diff --git a/app/src/main/java/io/github/sspanak/tt9/languages/EmojiLanguage.java b/app/src/main/java/io/github/sspanak/tt9/languages/EmojiLanguage.java index 1f3ff458..c0ce4add 100644 --- a/app/src/main/java/io/github/sspanak/tt9/languages/EmojiLanguage.java +++ b/app/src/main/java/io/github/sspanak/tt9/languages/EmojiLanguage.java @@ -1,11 +1,14 @@ package io.github.sspanak.tt9.languages; +import androidx.annotation.NonNull; + import java.util.ArrayList; import java.util.Locale; public class EmojiLanguage extends Language { final public static String EMOJI_SEQUENCE = "11"; - final public static String CUSTOM_EMOJI_SEQUENCE = EMOJI_SEQUENCE + "1"; + final private static int CUSTOM_EMOJI_KEY = 3; + final public static String CUSTOM_EMOJI_SEQUENCE = EMOJI_SEQUENCE + CUSTOM_EMOJI_KEY; public EmojiLanguage() { id = Integer.parseInt(EMOJI_SEQUENCE); @@ -23,4 +26,14 @@ public class EmojiLanguage extends Language { public ArrayList getKeyCharacters(int key, int characterGroup) { return key == 1 && characterGroup >= 0 ? new ArrayList<>(Characters.getEmoji(characterGroup)) : super.getKeyCharacters(key, characterGroup); } + + public static String validateEmojiSequence(@NonNull String sequence, int next) { + if (sequence.startsWith(CUSTOM_EMOJI_SEQUENCE) || (sequence.equals(EMOJI_SEQUENCE) && next == CUSTOM_EMOJI_KEY)) { + return CUSTOM_EMOJI_SEQUENCE; + } else if (sequence.startsWith(EMOJI_SEQUENCE) && (next > 1 || sequence.length() == Characters.getMaxEmojiLevel() + 1)) { + return sequence; + } else { + return sequence + next; + } + } } diff --git a/docs/user-manual.md b/docs/user-manual.md index 748a9581..175f7fc4 100644 --- a/docs/user-manual.md +++ b/docs/user-manual.md @@ -16,6 +16,8 @@ For more information, [see below](#language-options). ## Hotkeys +All hotkeys can be reconfigured or disabled from Settings → Keypad → Select Hotkeys. + #### Previous Suggestion key (Default: D-pad Left): Select the previous word/letter suggestion. @@ -49,16 +51,16 @@ _**Note2:** In messaging applications, you need to enable their "Send with ENTER - **In 123 mode:** - **Press:** type "0". - **Hold:** type special/math characters. - - **Hold "0", then Press "Next Mode" (Default: Hold "0", Press "#"):** type currency characters + - **Hold "0", then press "Next Mode" (Default: hold "0", press "#"):** type currency characters - **In ABC mode:** - **Press:** type space, newline or special/math characters. - **Hold:** type "0". - - **Press "0", then Press "Next Mode" (Default: Press "0", "#"):** type currency characters + - **Press "0", then press "Next Mode" (Default: press "0", "#"):** type currency characters - **In Predictive mode:** - **Press:** type space, newline or special/math characters. - - **Double Press:** type the character assigned in Predictive mode settings. (Default: ".") + - **Double press:** type the character assigned in Predictive mode settings. (Default: ".") - **Hold:** type "0". - - **Press "0", then press "Next Mode" (Default: Press "0", "#"):** type currency characters + - **Press "0", then press "Next Mode" (Default: press "0", "#"):** type currency characters #### 1-key: - **In 123 mode:** @@ -69,20 +71,19 @@ _**Note2:** In messaging applications, you need to enable their "Send with ENTER - **Hold:** type "1". - **In Predictive mode:** - **Press:** type sentence characters - - **Double Press:** type emoji - - **Triple Press:** type custom added emoji (you must have added some using [the Add Word key](#add-word-key-default-press-)) + - **Press multiple times:** type emoji + - **Press 1-1-3:** type custom added emoji (you must have added some using [the Add Word key](#add-word-key-default-press-)) - **Hold:** type "1". - - **Double Press "1", then press "Next Mode" (Default: Press "1", "1", then keep pressing "#"):** select between the predefined emoji groups #### 2- to 9-key: - **In 123 mode:** type the respective number -- **In ABC and Predictive mode:** type a letter character or hold to type the respective number. +- **In ABC and Predictive mode:** type a letter or hold to type the respective number. -#### Add Word Key (Default: Press ✱): +#### Add Word Key (Default: press ✱): Add a new word to the dictionary for the current language. -You can also add new emoji. Then access them by pressing 1-1-# (change "#" with the "Next Mode" key, if you have changed the default). Regardless of the selected language at the time of adding, all emoji will be available in all languages. +You can also add new emoji and then access them by pressing 1-1-3. Regardless of the currently selected language, all emoji will be available in all languages. #### Backspace Key: Just deletes text. @@ -97,15 +98,15 @@ _**NB 2:** Holding "Back" key will always trigger the default system action (i.e _In these cases, you could assign another key (all other keys are fully usable), or use the on-screen backspace._ -#### Next Input Mode Key (Default: Press #): +#### Next Input Mode Key (Default: press #): - **Press when there are no suggestions:** Cycle the input modes (abc → ABC → Predictive → 123). Note that only 123 mode is available in numeric fields and Predictive mode is not available in password fields. - **Press while suggestions are on:** Toggle the suggestions between UPPERCASE and lowercase. In case the suggestions are only special characters, switch to the next character group. - **Number-only fields:** No special action. Type a "#" with the default key. Changing the mode is not possible in such fields. -#### Next Language Key (Default: Hold #): +#### Next Language Key (Default: hold #): Select the next language, when multiple languages have been enabled from the Settings. -#### Settings Key (Default: Hold ✱): +#### Settings Key (Default: hold ✱): Open the Settings configuration screen. #### Change Keyboard Key (Default: _unassigned_): @@ -114,7 +115,7 @@ Open the Android Change Keyboard dialog where you can select between all install ## On-screen Keypad On touchscreen-only phones, a fully functional on-screen keypad is available. Enable it from Settings → Appearance → Show On-Screen Numpad. -It is also recommended to disable the special behavior of "Back" key working as "Backspace". It is useful only for a hardware keypad. To do so, go to: Settings → Keyboard → Select Hotkeys → Backspace key, then select the "--" option. +It is also recommended to disable the special behavior of "Back" key working as "Backspace". It is useful only for a hardware keypad. To do so, go to: Settings → Keypad → Select Hotkeys → Backspace key, then select the "--" option. If you do have a hardware keypad and prefer having more screen space, disable the software keys from the Settings → Appearance.