added currency character typing in all modes
This commit is contained in:
parent
e03c788ebb
commit
a3e72283f8
11 changed files with 160 additions and 101 deletions
|
|
@ -196,7 +196,7 @@ public class DictionaryLoader {
|
||||||
WordBatch letters = new WordBatch(language);
|
WordBatch letters = new WordBatch(language);
|
||||||
|
|
||||||
for (int key = 2; key <= 9; key++) {
|
for (int key = 2; key <= 9; key++) {
|
||||||
for (String langChar : language.getKeyCharacters(key, false)) {
|
for (String langChar : language.getKeyCharacters(key)) {
|
||||||
langChar = (isEnglish && langChar.equals("i")) ? langChar.toUpperCase(Locale.ENGLISH) : langChar;
|
langChar = (isEnglish && langChar.equals("i")) ? langChar.toUpperCase(Locale.ENGLISH) : langChar;
|
||||||
letters.add(langChar, 0, key);
|
letters.add(langChar, 0, key);
|
||||||
lettersCount++;
|
lettersCount++;
|
||||||
|
|
|
||||||
|
|
@ -688,10 +688,6 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void refreshComposingText() {
|
|
||||||
textField.setComposingText(getComposingText());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void setComposingTextWithHighlightedStem(@NonNull String word) {
|
private void setComposingTextWithHighlightedStem(@NonNull String word) {
|
||||||
if (appHacks.setComposingTextWithHighlightedStem(word)) {
|
if (appHacks.setComposingTextWithHighlightedStem(word)) {
|
||||||
|
|
@ -718,7 +714,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
for (int retries = 0; retries < 2 && mLanguage.hasUpperCase(); retries++) {
|
for (int retries = 0; retries < 2 && mLanguage.hasUpperCase(); retries++) {
|
||||||
mInputMode.nextTextCase();
|
mInputMode.nextTextCase();
|
||||||
setSuggestions(mInputMode.getSuggestions(), suggestionBar.getCurrentIndex());
|
setSuggestions(mInputMode.getSuggestions(), suggestionBar.getCurrentIndex());
|
||||||
refreshComposingText();
|
textField.setComposingText(suggestionBar.getCurrentSuggestion());
|
||||||
|
|
||||||
if (!currentSuggestionBefore.equals(getComposingText())) {
|
if (!currentSuggestionBefore.equals(getComposingText())) {
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,10 @@ abstract public class InputMode {
|
||||||
|
|
||||||
// data
|
// data
|
||||||
protected int autoAcceptTimeout = -1;
|
protected int autoAcceptTimeout = -1;
|
||||||
|
@NonNull protected String digitSequence = "";
|
||||||
protected Language language;
|
protected Language language;
|
||||||
protected final ArrayList<String> suggestions = new ArrayList<>();
|
protected final ArrayList<String> suggestions = new ArrayList<>();
|
||||||
|
protected int specialCharSelectedGroup = 0;
|
||||||
|
|
||||||
|
|
||||||
public static InputMode getInstance(SettingsStore settings, Language language, InputType inputType, int mode) {
|
public static InputMode getInstance(SettingsStore settings, Language language, InputType inputType, int mode) {
|
||||||
|
|
@ -44,7 +46,7 @@ abstract public class InputMode {
|
||||||
default:
|
default:
|
||||||
Logger.w("InputMode", "Defaulting to mode: " + Mode123.class.getName() + " for unknown InputMode: " + mode);
|
Logger.w("InputMode", "Defaulting to mode: " + Mode123.class.getName() + " for unknown InputMode: " + mode);
|
||||||
case MODE_123:
|
case MODE_123:
|
||||||
return new Mode123(inputType);
|
return new Mode123(inputType, language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,6 +104,7 @@ abstract public class InputMode {
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
autoAcceptTimeout = -1;
|
autoAcceptTimeout = -1;
|
||||||
|
specialCharSelectedGroup = 0;
|
||||||
suggestions.clear();
|
suggestions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -125,9 +128,40 @@ abstract public class InputMode {
|
||||||
textCase = allowedTextCases.get(0);
|
textCase = allowedTextCases.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void nextTextCase() {
|
public boolean nextTextCase() {
|
||||||
|
if (nextSpecialCharacters()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int nextIndex = (allowedTextCases.indexOf(textCase) + 1) % allowedTextCases.size();
|
int nextIndex = (allowedTextCases.indexOf(textCase) + 1) % allowedTextCases.size();
|
||||||
textCase = allowedTextCases.get(nextIndex);
|
textCase = allowedTextCases.get(nextIndex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used in nextTextCase() for switching to the next set of characters. Obviously,
|
||||||
|
* special chars do not have a text case, but we use this trick to alternate the char groups.
|
||||||
|
*/
|
||||||
|
protected boolean nextSpecialCharacters() {
|
||||||
|
if (language == null || digitSequence.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int key = digitSequence.charAt(0) - '0';
|
||||||
|
|
||||||
|
ArrayList<String> chars = language.getKeyCharacters(key, ++specialCharSelectedGroup);
|
||||||
|
if (chars.isEmpty() && specialCharSelectedGroup == 1) {
|
||||||
|
specialCharSelectedGroup = 0;
|
||||||
|
return false;
|
||||||
|
} else if (chars.isEmpty()) {
|
||||||
|
specialCharSelectedGroup = 0;
|
||||||
|
chars = language.getKeyCharacters(key, specialCharSelectedGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
suggestions.clear();
|
||||||
|
suggestions.addAll(chars);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void determineNextWordTextCase(String textBeforeCursor) {}
|
public void determineNextWordTextCase(String textBeforeCursor) {}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import java.util.Collections;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.ime.helpers.InputType;
|
||||||
import io.github.sspanak.tt9.languages.Characters;
|
import io.github.sspanak.tt9.languages.Characters;
|
||||||
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
|
||||||
public class Mode123 extends ModePassthrough {
|
public class Mode123 extends ModePassthrough {
|
||||||
@Override public int getId() { return MODE_123; }
|
@Override public int getId() { return MODE_123; }
|
||||||
|
|
@ -21,7 +22,9 @@ public class Mode123 extends ModePassthrough {
|
||||||
private final ArrayList<ArrayList<String>> KEY_CHARACTERS = new ArrayList<>();
|
private final ArrayList<ArrayList<String>> KEY_CHARACTERS = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
public Mode123(InputType inputType) {
|
public Mode123(InputType inputType, Language language) {
|
||||||
|
this.language = language;
|
||||||
|
|
||||||
if (inputType.isPhoneNumber()) {
|
if (inputType.isPhoneNumber()) {
|
||||||
getPhoneSpecialCharacters();
|
getPhoneSpecialCharacters();
|
||||||
} else if (inputType.isNumeric()) {
|
} else if (inputType.isNumeric()) {
|
||||||
|
|
@ -79,14 +82,20 @@ public class Mode123 extends ModePassthrough {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean nextSpecialCharacters() {
|
||||||
|
return digitSequence.equals(Language.SPECIAL_CHARS_KEY) && super.nextSpecialCharacters();
|
||||||
|
}
|
||||||
|
|
||||||
@Override public boolean onNumber(int number, boolean hold, int repeat) {
|
@Override public boolean onNumber(int number, boolean hold, int repeat) {
|
||||||
reset();
|
reset();
|
||||||
|
digitSequence = String.valueOf(number);
|
||||||
|
|
||||||
if (hold && number < KEY_CHARACTERS.size() && KEY_CHARACTERS.get(number).size() > 0) {
|
if (hold && number < KEY_CHARACTERS.size() && KEY_CHARACTERS.get(number).size() > 0) {
|
||||||
suggestions.addAll(KEY_CHARACTERS.get(number));
|
suggestions.addAll(KEY_CHARACTERS.get(number));
|
||||||
} else {
|
} else {
|
||||||
autoAcceptTimeout = 0;
|
autoAcceptTimeout = 0;
|
||||||
suggestions.add(String.valueOf(number));
|
suggestions.add(digitSequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -111,4 +120,11 @@ public class Mode123 extends ModePassthrough {
|
||||||
|| (text.charAt(0) > 122 && text.charAt(0) < 127)
|
|| (text.charAt(0) > 122 && text.charAt(0) < 127)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
super.reset();
|
||||||
|
digitSequence = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ public class ModeABC extends InputMode {
|
||||||
public boolean onNumber(int number, boolean hold, int repeat) {
|
public boolean onNumber(int number, boolean hold, int repeat) {
|
||||||
if (hold) {
|
if (hold) {
|
||||||
reset();
|
reset();
|
||||||
|
digitSequence = String.valueOf(number);
|
||||||
suggestions.add(language.getKeyNumber(number));
|
suggestions.add(language.getKeyNumber(number));
|
||||||
autoAcceptTimeout = 0;
|
autoAcceptTimeout = 0;
|
||||||
} else if (repeat > 0) {
|
} else if (repeat > 0) {
|
||||||
|
|
@ -28,7 +29,9 @@ public class ModeABC extends InputMode {
|
||||||
autoAcceptTimeout = settings.getAbcAutoAcceptTimeout();
|
autoAcceptTimeout = settings.getAbcAutoAcceptTimeout();
|
||||||
} else {
|
} else {
|
||||||
reset();
|
reset();
|
||||||
|
digitSequence = String.valueOf(number);
|
||||||
suggestions.addAll(language.getKeyCharacters(number));
|
suggestions.addAll(language.getKeyCharacters(number));
|
||||||
|
suggestions.add(language.getKeyNumber(number));
|
||||||
autoAcceptTimeout = settings.getAbcAutoAcceptTimeout();
|
autoAcceptTimeout = settings.getAbcAutoAcceptTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,6 +43,16 @@ public class ModeABC extends InputMode {
|
||||||
return newTextCase == CASE_UPPER ? word.toUpperCase(language.getLocale()) : word.toLowerCase(language.getLocale());
|
return newTextCase == CASE_UPPER ? word.toUpperCase(language.getLocale()) : word.toLowerCase(language.getLocale());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean nextSpecialCharacters() {
|
||||||
|
if (digitSequence.equals(Language.SPECIAL_CHARS_KEY) && super.nextSpecialCharacters()) {
|
||||||
|
suggestions.add(language.getKeyNumber(digitSequence.charAt(0) - '0'));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void changeLanguage(Language language) {
|
public void changeLanguage(Language language) {
|
||||||
super.changeLanguage(language);
|
super.changeLanguage(language);
|
||||||
|
|
@ -59,6 +72,7 @@ public class ModeABC extends InputMode {
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
super.reset();
|
super.reset();
|
||||||
|
digitSequence = "";
|
||||||
shouldSelectNextLetter = false;
|
shouldSelectNextLetter = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,20 @@ 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;
|
||||||
import io.github.sspanak.tt9.ime.modes.helpers.Predictions;
|
import io.github.sspanak.tt9.ime.modes.helpers.Predictions;
|
||||||
|
import io.github.sspanak.tt9.languages.Characters;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
public class ModePredictive extends InputMode {
|
public class ModePredictive extends InputMode {
|
||||||
private final String LOG_TAG = getClass().getSimpleName();
|
private final String LOG_TAG = getClass().getSimpleName();
|
||||||
|
|
||||||
|
private final static String PREFERRED_CHAR_SEQUENCE = "00";
|
||||||
|
private final static String EMOJI_SEQUENCE = "11";
|
||||||
|
|
||||||
private final SettingsStore settings;
|
private final SettingsStore settings;
|
||||||
|
|
||||||
public int getId() { return MODE_PREDICTIVE; }
|
public int getId() { return MODE_PREDICTIVE; }
|
||||||
|
|
||||||
private String digitSequence = "";
|
|
||||||
private String lastAcceptedWord = "";
|
private String lastAcceptedWord = "";
|
||||||
|
|
||||||
// stem filter
|
// stem filter
|
||||||
|
|
@ -46,9 +49,11 @@ public class ModePredictive extends InputMode {
|
||||||
|
|
||||||
autoSpace = new AutoSpace(settings);
|
autoSpace = new AutoSpace(settings);
|
||||||
autoTextCase = new AutoTextCase(settings);
|
autoTextCase = new AutoTextCase(settings);
|
||||||
predictions = new Predictions(settings);
|
predictions = new Predictions();
|
||||||
|
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
|
|
||||||
|
digitSequence = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -205,10 +210,8 @@ public class ModePredictive extends InputMode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* loadSuggestions
|
* loadSuggestions
|
||||||
* Loads the possible list of suggestions for the current digitSequence.
|
* Loads the possible list of suggestions for the current digitSequence. "currentWord" is used
|
||||||
* Returns "false" on invalid sequence.
|
* for generating suggestions when there are no results.
|
||||||
*
|
|
||||||
* "currentWord" is used for generating suggestions when there are no results.
|
|
||||||
* See: Predictions.generatePossibleCompletions()
|
* See: Predictions.generatePossibleCompletions()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -218,6 +221,10 @@ public class ModePredictive extends InputMode {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (loadStaticSuggestions(onLoad)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
onSuggestionsUpdated = onLoad;
|
onSuggestionsUpdated = onLoad;
|
||||||
predictions
|
predictions
|
||||||
.setDigitSequence(digitSequence)
|
.setDigitSequence(digitSequence)
|
||||||
|
|
@ -229,6 +236,29 @@ public class ModePredictive extends InputMode {
|
||||||
.load();
|
.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* loadStatic
|
||||||
|
* Loads words that are not in the database and are supposed to be in the same order, such as
|
||||||
|
* emoji or the preferred character for double "0". Returns "false", when there are no static
|
||||||
|
* options for the current digitSequence.
|
||||||
|
*/
|
||||||
|
private boolean loadStaticSuggestions(Runnable onLoad) {
|
||||||
|
if (digitSequence.startsWith(EMOJI_SEQUENCE)) {
|
||||||
|
digitSequence = digitSequence.substring(0, Math.min(digitSequence.length(), Characters.getEmojiLevels() + 1));
|
||||||
|
specialCharSelectedGroup = digitSequence.length() - 2;
|
||||||
|
super.nextSpecialCharacters();
|
||||||
|
onLoad.run();
|
||||||
|
return true;
|
||||||
|
} else if (digitSequence.startsWith(PREFERRED_CHAR_SEQUENCE)) {
|
||||||
|
suggestions.clear();
|
||||||
|
suggestions.add(settings.getDoubleZeroChar());
|
||||||
|
onLoad.run();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getPredictions
|
* getPredictions
|
||||||
|
|
@ -270,7 +300,7 @@ public class ModePredictive extends InputMode {
|
||||||
|
|
||||||
// emoji and punctuation are not in the database, so there is no point in
|
// emoji and punctuation are not in the database, so there is no point in
|
||||||
// running queries that would update nothing
|
// running queries that would update nothing
|
||||||
if (!sequence.startsWith("11") && !sequence.equals("1") && !sequence.startsWith("0")) {
|
if (!sequence.startsWith(Language.PUNCTUATION_KEY) && !sequence.startsWith(Language.SPECIAL_CHARS_KEY)) {
|
||||||
WordStoreAsync.makeTopWord(language, currentWord, sequence);
|
WordStoreAsync.makeTopWord(language, currentWord, sequence);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
@ -284,6 +314,11 @@ public class ModePredictive extends InputMode {
|
||||||
return autoTextCase.adjustSuggestionTextCase(language, word, newTextCase);
|
return autoTextCase.adjustSuggestionTextCase(language, word, newTextCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean nextSpecialCharacters() {
|
||||||
|
return digitSequence.equals(Language.SPECIAL_CHARS_KEY) && super.nextSpecialCharacters();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void determineNextWordTextCase(String textBeforeCursor) {
|
public void determineNextWordTextCase(String textBeforeCursor) {
|
||||||
textCase = autoTextCase.determineNextWordTextCase(textCase, textFieldTextCase, textBeforeCursor);
|
textCase = autoTextCase.determineNextWordTextCase(textCase, textFieldTextCase, textBeforeCursor);
|
||||||
|
|
@ -296,12 +331,14 @@ public class ModePredictive extends InputMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextTextCase() {
|
public boolean nextTextCase() {
|
||||||
textFieldTextCase = CASE_UNDEFINED; // since it's a user's choice, the default matters no more
|
boolean changed = super.nextTextCase();
|
||||||
super.nextTextCase();
|
textFieldTextCase = changed ? CASE_UNDEFINED : textFieldTextCase; // since it's a user's choice, the default matters no more
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shouldAcceptPreviousSuggestion
|
* shouldAcceptPreviousSuggestion
|
||||||
* Automatic space assistance. Spaces (and special chars) cause suggestions to be accepted
|
* Automatic space assistance. Spaces (and special chars) cause suggestions to be accepted
|
||||||
|
|
@ -329,7 +366,7 @@ public class ModePredictive extends InputMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
// special characters always break words
|
// special characters always break words
|
||||||
if (autoAcceptTimeout == 0 && !digitSequence.startsWith("0")) {
|
if (autoAcceptTimeout == 0 && !digitSequence.startsWith(Language.SPECIAL_CHARS_KEY)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,14 +374,14 @@ public class ModePredictive extends InputMode {
|
||||||
if (language.isHebrew() || language.isUkrainian()) {
|
if (language.isHebrew() || language.isUkrainian()) {
|
||||||
return
|
return
|
||||||
predictions.noDbWords()
|
predictions.noDbWords()
|
||||||
&& digitSequence.equals("1");
|
&& digitSequence.equals(Language.PUNCTUATION_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// punctuation breaks words, unless there are database matches ('s, qu', по-, etc...)
|
// punctuation breaks words, unless there are database matches ('s, qu', по-, etc...)
|
||||||
return
|
return
|
||||||
!digitSequence.isEmpty()
|
!digitSequence.isEmpty()
|
||||||
&& predictions.noDbWords()
|
&& predictions.noDbWords()
|
||||||
&& digitSequence.contains("1")
|
&& digitSequence.contains(Language.PUNCTUATION_KEY)
|
||||||
&& TextTools.containsOtherThan1(digitSequence);
|
&& TextTools.containsOtherThan1(digitSequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
package io.github.sspanak.tt9.ime.modes.helpers;
|
package io.github.sspanak.tt9.ime.modes.helpers;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import io.github.sspanak.tt9.db.WordStoreAsync;
|
import io.github.sspanak.tt9.db.WordStoreAsync;
|
||||||
import io.github.sspanak.tt9.ime.EmptyDatabaseWarning;
|
import io.github.sspanak.tt9.ime.EmptyDatabaseWarning;
|
||||||
import io.github.sspanak.tt9.languages.Characters;
|
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
public class Predictions {
|
public class Predictions {
|
||||||
private final EmptyDatabaseWarning emptyDbWarning;
|
private final EmptyDatabaseWarning emptyDbWarning;
|
||||||
private final SettingsStore settings;
|
|
||||||
|
|
||||||
private Language language;
|
private Language language;
|
||||||
private String digitSequence;
|
private String digitSequence;
|
||||||
|
|
@ -26,22 +23,9 @@ public class Predictions {
|
||||||
private boolean areThereDbWords = false;
|
private boolean areThereDbWords = false;
|
||||||
private ArrayList<String> words = new ArrayList<>();
|
private ArrayList<String> words = new ArrayList<>();
|
||||||
|
|
||||||
// punctuation/emoji
|
|
||||||
private final Pattern containsOnly1Regex = Pattern.compile("^1+$");
|
|
||||||
private final String maxEmojiSequence;
|
|
||||||
|
|
||||||
|
public Predictions() {
|
||||||
public Predictions(SettingsStore settingsStore) {
|
|
||||||
emptyDbWarning = new EmptyDatabaseWarning();
|
emptyDbWarning = new EmptyDatabaseWarning();
|
||||||
settings = settingsStore;
|
|
||||||
|
|
||||||
// digitSequence limiter when selecting emoji
|
|
||||||
// "11" = Emoji level 0, "111" = Emoji level 1,... up to the maximum amount of 1s
|
|
||||||
StringBuilder maxEmojiSequenceBuilder = new StringBuilder();
|
|
||||||
for (int i = 0; i <= Characters.getEmojiLevels(); i++) {
|
|
||||||
maxEmojiSequenceBuilder.append("1");
|
|
||||||
}
|
|
||||||
maxEmojiSequence = maxEmojiSequenceBuilder.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -125,54 +109,15 @@ public class Predictions {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadStatic()) {
|
WordStoreAsync.getWords(
|
||||||
onWordsChanged.run();
|
(words) -> onDbWords(words, true),
|
||||||
} else {
|
language,
|
||||||
WordStoreAsync.getWords(
|
digitSequence,
|
||||||
(words) -> onDbWords(words, true),
|
stem,
|
||||||
language,
|
SettingsStore.SUGGESTIONS_MIN,
|
||||||
digitSequence,
|
SettingsStore.SUGGESTIONS_MAX
|
||||||
stem,
|
);
|
||||||
SettingsStore.SUGGESTIONS_MIN,
|
|
||||||
SettingsStore.SUGGESTIONS_MAX
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* loadStatic
|
|
||||||
* Similar to "load()", but loads words that are not in the database.
|
|
||||||
* Returns "false", when there are no static options for the current digitSequence.
|
|
||||||
*/
|
|
||||||
private boolean loadStatic() {
|
|
||||||
// whitespace/special/math characters
|
|
||||||
if (digitSequence.equals("0")) {
|
|
||||||
stem = "";
|
|
||||||
words.clear();
|
|
||||||
words.addAll(language.getKeyCharacters(0, false));
|
|
||||||
}
|
|
||||||
// "00" is a shortcut for the preferred character
|
|
||||||
else if (digitSequence.equals("00")) {
|
|
||||||
stem = "";
|
|
||||||
words.clear();
|
|
||||||
words.add(settings.getDoubleZeroChar());
|
|
||||||
}
|
|
||||||
// emoji
|
|
||||||
else if (containsOnly1Regex.matcher(digitSequence).matches()) {
|
|
||||||
stem = "";
|
|
||||||
words.clear();
|
|
||||||
if (digitSequence.length() == 1) {
|
|
||||||
words.addAll(language.getKeyCharacters(1, false));
|
|
||||||
} else {
|
|
||||||
digitSequence = digitSequence.length() <= maxEmojiSequence.length() ? digitSequence : maxEmojiSequence;
|
|
||||||
words.addAll(Characters.getEmoji(digitSequence.length() - 2));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadWithoutLeadingPunctuation() {
|
private void loadWithoutLeadingPunctuation() {
|
||||||
|
|
@ -242,7 +187,7 @@ public class Predictions {
|
||||||
|
|
||||||
// append all letters for the last digit in the sequence (the last pressed key)
|
// append all letters for the last digit in the sequence (the last pressed key)
|
||||||
int lastSequenceDigit = digitSequence.charAt(digitSequence.length() - 1) - '0';
|
int lastSequenceDigit = digitSequence.charAt(digitSequence.length() - 1) - '0';
|
||||||
for (String keyLetter : language.getKeyCharacters(lastSequenceDigit, false)) {
|
for (String keyLetter : language.getKeyCharacters(lastSequenceDigit)) {
|
||||||
generatedWords.add(baseWord + keyLetter);
|
generatedWords.add(baseWord + keyLetter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,12 @@ public class Characters {
|
||||||
",", ".", "-", "„", "“", "(", ")", "[", "]", "&", "~", "`", "'", ";", ":", "!", "?"
|
",", ".", "-", "„", "“", "(", ")", "[", "]", "&", "~", "`", "'", ";", ":", "!", "?"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
final public static ArrayList<String> Currency = new ArrayList<>(Arrays.asList(
|
||||||
|
"$", "€", "₹", "₿", "₺", "₱", "¥", "₽", "£"
|
||||||
|
));
|
||||||
|
|
||||||
final public static ArrayList<String> Special = new ArrayList<>(Arrays.asList(
|
final public static ArrayList<String> Special = new ArrayList<>(Arrays.asList(
|
||||||
" ", "\n", "@", "_", "#", "%", "$", "{", "}", "|", "^", "<", ">", "\\", "/", "=", "*", "+"
|
" ", "\n", "@", "_", "#", "%", "{", "}", "|", "^", "<", ">", "\\", "/", "=", "*", "+"
|
||||||
));
|
));
|
||||||
|
|
||||||
final private static ArrayList<String> TextEmoticons = new ArrayList<>(Arrays.asList(
|
final private static ArrayList<String> TextEmoticons = new ArrayList<>(Arrays.asList(
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ import java.util.Locale;
|
||||||
|
|
||||||
|
|
||||||
public class Language {
|
public class Language {
|
||||||
|
public static String SPECIAL_CHARS_KEY = "0";
|
||||||
|
public static String PUNCTUATION_KEY = "1";
|
||||||
|
|
||||||
private int id;
|
private int id;
|
||||||
protected String name;
|
protected String name;
|
||||||
protected Locale locale;
|
protected Locale locale;
|
||||||
|
|
@ -120,7 +123,7 @@ public class Language {
|
||||||
|
|
||||||
final public String getAbcString() {
|
final public String getAbcString() {
|
||||||
if (abcString == null) {
|
if (abcString == null) {
|
||||||
ArrayList<String> lettersList = getKeyCharacters(2, false);
|
ArrayList<String> lettersList = getKeyCharacters(2);
|
||||||
|
|
||||||
abcString = "";
|
abcString = "";
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
@ -143,11 +146,11 @@ public class Language {
|
||||||
* Returns "true" when the language is based on the Latin alphabet or "false" otherwise.
|
* Returns "true" when the language is based on the Latin alphabet or "false" otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isLatinBased() {
|
public boolean isLatinBased() {
|
||||||
return getKeyCharacters(2, false).contains("a");
|
return getKeyCharacters(2).contains("a");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCyrillic() {
|
public boolean isCyrillic() {
|
||||||
return getKeyCharacters(2, false).contains("а");
|
return getKeyCharacters(2).contains("а");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRTL() {
|
public boolean isRTL() {
|
||||||
|
|
@ -155,19 +158,19 @@ public class Language {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGreek() {
|
public boolean isGreek() {
|
||||||
return getKeyCharacters(2, false).contains("α");
|
return getKeyCharacters(2).contains("α");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isArabic() {
|
public boolean isArabic() {
|
||||||
return getKeyCharacters(3, false).contains("ا");
|
return getKeyCharacters(3).contains("ا");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUkrainian() {
|
public boolean isUkrainian() {
|
||||||
return getKeyCharacters(3, false).contains("є");
|
return getKeyCharacters(3).contains("є");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHebrew() {
|
public boolean isHebrew() {
|
||||||
return getKeyCharacters(3, false).contains("א");
|
return getKeyCharacters(3).contains("א");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************ utility ************ */
|
/* ************ utility ************ */
|
||||||
|
|
@ -240,21 +243,27 @@ public class Language {
|
||||||
return word != null && word.toUpperCase(locale).equals(word);
|
return word != null && word.toUpperCase(locale).equals(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<String> getKeyCharacters(int key, boolean includeDigit) {
|
public ArrayList<String> getKeyCharacters(int key, int characterGroup) {
|
||||||
if (key < 0 || key >= layout.size()) {
|
if (key < 0 || key >= layout.size()) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<String> chars = new ArrayList<>(layout.get(key));
|
ArrayList<String> chars = new ArrayList<>(layout.get(key));
|
||||||
if (includeDigit && chars.size() > 0) {
|
if (characterGroup > 0) {
|
||||||
chars.add(getKeyNumber(key));
|
if (key == 0 && characterGroup == 1) {
|
||||||
|
chars = new ArrayList<>(Characters.Currency);
|
||||||
|
} else if (key == 1) {
|
||||||
|
chars = new ArrayList<>(Characters.getEmoji(characterGroup - 1));
|
||||||
|
} else {
|
||||||
|
chars = new ArrayList<>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return chars;
|
return chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<String> getKeyCharacters(int key) {
|
public ArrayList<String> getKeyCharacters(int key) {
|
||||||
return getKeyCharacters(key, true);
|
return getKeyCharacters(key, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getKeyNumber(int key) {
|
public String getKeyNumber(int key) {
|
||||||
|
|
@ -285,6 +294,7 @@ public class Language {
|
||||||
return sequence.toString();
|
return sequence.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ public class SoftNumberKey extends SoftKey {
|
||||||
boolean isGreekBased = language.isGreek();
|
boolean isGreekBased = language.isGreek();
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
ArrayList<String> chars = language.getKeyCharacters(number, false);
|
ArrayList<String> chars = language.getKeyCharacters(number);
|
||||||
for (int i = 0; i < 5 && i < chars.size(); i++) {
|
for (int i = 0; i < 5 && i < chars.size(); i++) {
|
||||||
String currentLetter = chars.get(i);
|
String currentLetter = chars.get(i);
|
||||||
if (
|
if (
|
||||||
|
|
|
||||||
|
|
@ -73,13 +73,16 @@ _**Note3:** Facebook Messenger supports sending messages with the keypad only on
|
||||||
- **In 123 mode:**
|
- **In 123 mode:**
|
||||||
- **Press:** type "0".
|
- **Press:** type "0".
|
||||||
- **Hold:** type special/math characters.
|
- **Hold:** type special/math characters.
|
||||||
|
- **Hold "0", then Press "Next Mode" (Default: Hold "0", Press "#"):** type currency characters
|
||||||
- **In ABC mode:**
|
- **In ABC mode:**
|
||||||
- **Press:** type space, newline or special/math characters.
|
- **Press:** type space, newline or special/math characters.
|
||||||
- **Hold:** type "0".
|
- **Hold:** type "0".
|
||||||
|
- **Press "0", then Press "Next Mode" (Default: Press "0", "#"):** type currency characters
|
||||||
- **In Predictive mode:**
|
- **In Predictive mode:**
|
||||||
- **Press:** type space, newline or special/math characters.
|
- **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".
|
- **Hold:** type "0".
|
||||||
|
- **Press "0", then Press "Next Mode" (Default: Press "0", "#"):** type currency characters
|
||||||
|
|
||||||
#### 1- to 9-key:
|
#### 1- to 9-key:
|
||||||
- **In 123 mode:** type the respective number or hold to type punctuation.
|
- **In 123 mode:** type the respective number or hold to type punctuation.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue