1
0
Fork 0

expanding the special chars now works

This commit is contained in:
sspanak 2025-05-08 18:47:48 +03:00 committed by Dimo Karaivanov
parent aecc350b91
commit fb90217610
20 changed files with 111 additions and 87 deletions

View file

@ -17,6 +17,7 @@ import io.github.sspanak.tt9.ui.main.ResizableMainView;
import io.github.sspanak.tt9.ui.tray.SuggestionsBar;
import io.github.sspanak.tt9.util.ConsumerCompat;
import io.github.sspanak.tt9.util.Text;
import io.github.sspanak.tt9.util.chars.Characters;
public class SuggestionOps {
@NonNull private final Handler delayedAcceptHandler;
@ -112,6 +113,10 @@ public class SuggestionOps {
public String acceptCurrent() {
String word = getCurrent();
if (Characters.PLACEHOLDER.equals(word)) {
return "";
}
if (!word.isEmpty()) {
commitCurrent(true, true);
}
@ -122,6 +127,10 @@ public class SuggestionOps {
public String acceptIncomplete() {
String currentWord = this.getCurrent();
if (Characters.PLACEHOLDER.equals(currentWord)) {
return "";
}
commitCurrent(false, true);
return currentWord;
@ -129,6 +138,10 @@ public class SuggestionOps {
public String acceptIncompleteAndKeepList() {
if (Characters.PLACEHOLDER.equals(this.getCurrent())) {
return "";
}
commitCurrent(false, false);
return this.getCurrent();
}
@ -140,6 +153,9 @@ public class SuggestionOps {
}
String lastComposingText = getCurrent(language, sequenceLength - 1);
if (Characters.PLACEHOLDER.equals(lastComposingText)) {
return "";
}
commitCurrent(false, true);
return lastComposingText;
}

View file

@ -86,14 +86,23 @@ abstract public class InputMode {
public void onAcceptSuggestion(@NonNull String word) { onAcceptSuggestion(word, false); }
public void onAcceptSuggestion(@NonNull String word, boolean preserveWordList) {}
public void onCursorMove(@NonNull String word) { if (!digitSequence.isEmpty()) onAcceptSuggestion(word); }
public void onReplaceSuggestion(@NonNull String rawWord) {
if (SuggestionsBar.SHOW_SPECIAL_CHARS_SUGGESTION.equals(rawWord)) {
Logger.d("InputMode", "Loading special characters for: " + seq.SPECIAL_CHAR_SEQUENCE);
public boolean onReplaceSuggestion(@NonNull String rawWord) {
reset();
boolean result = false;
if (rawWord.equals(SuggestionsBar.SHOW_SPECIAL_CHARS_SUGGESTION)) {
digitSequence = seq.SPECIAL_CHAR_SEQUENCE;
loadSpecialCharacters();
result = true;
} else if (rawWord.equals(SuggestionsBar.SHOW_CURRENCIES_SUGGESTION)) {
digitSequence = seq.CURRENCY_SEQUENCE;
loadSpecialCharacters();
result = true;
}
if (SuggestionsBar.SHOW_CURRENCIES_SUGGESTION.equals(rawWord)) {
Logger.d("InputMode", "Loading special characters for: " + seq.CURRENCY_SEQUENCE);
}
onSuggestionsUpdated.run();
return result;
}
/**
@ -208,9 +217,20 @@ abstract public class InputMode {
}
/**
* Loads the special characters for 0-key or 1-key. For 0-key, this could be a minimized (show more)
* special character list, or the whitespace list.
*/
protected boolean loadSpecialCharacters() {
suggestions.clear();
suggestions.addAll(settings.getOrderedKeyChars(language, digitSequence.charAt(0) - '0'));
if (digitSequence.equals(seq.SPECIAL_CHAR_SEQUENCE) || digitSequence.equals(seq.PUNCTUATION_SEQUENCE)) {
suggestions.addAll(settings.getOrderedKeyChars(language, digitSequence.charAt(0) - '0'));
} else if (digitSequence.equals(seq.CURRENCY_SEQUENCE)) {
suggestions.addAll(Characters.getCurrencies(language));
} else {
suggestions.addAll(getAbbreviatedSpecialChars());
}
return true;
}

View file

@ -70,9 +70,9 @@ public class ModeBopomofo extends ModePinyin {
@Override
protected void onNumberPress(int nextNumber) {
if (digitSequence.startsWith(seq.PUNCTUATION_SEQUENCE)) {
if (seq.startsWithEmojiSequence(digitSequence)) {
digitSequence = EmojiLanguage.validateEmojiSequence(seq, digitSequence, nextNumber);
} else {
} else if (!seq.SPECIAL_CHAR_SEQUENCE.equals(digitSequence) && !seq.CURRENCY_SEQUENCE.equals(digitSequence)) {
digitSequence += String.valueOf(nextNumber);
}
}

View file

@ -99,7 +99,9 @@ class ModeCheonjiin extends InputMode {
@Override
public boolean onBackspace() {
if (digitSequence.equals(seq.PUNCTUATION_SEQUENCE)) {
if (digitSequence.equals(seq.CURRENCY_SEQUENCE) || digitSequence.equals(seq.SPECIAL_CHAR_SEQUENCE)) {
digitSequence = seq.WHITESPACE_SEQUENCE;
} else if (digitSequence.equals(seq.PUNCTUATION_SEQUENCE)) {
digitSequence = "";
} else if (digitSequence.equals(seq.WHITESPACE_SEQUENCE) || (!digitSequence.startsWith(seq.PUNCTUATION_SEQUENCE) && Cheonjiin.isSingleJamo(digitSequence))) {
digitSequence = "";
@ -148,23 +150,27 @@ class ModeCheonjiin extends InputMode {
digitSequence = digitSequence.substring(0, digitSequence.length() - rewindAmount);
}
if (digitSequence.startsWith(seq.PUNCTUATION_SEQUENCE)) {
if (seq.startsWithEmojiSequence(digitSequence)) {
digitSequence = EmojiLanguage.validateEmojiSequence(seq, digitSequence, nextNumber);
} else {
} else if (!seq.SPECIAL_CHAR_SEQUENCE.equals(digitSequence) && !seq.CURRENCY_SEQUENCE.equals(digitSequence)) {
digitSequence += String.valueOf(nextNumber);
}
if (seq.PREFERRED_CHAR_SEQUENCE.equals(digitSequence)) {
autoAcceptTimeout = 0;
}
}
private int shouldRewindRepeatingNumbers(int nextNumber) {
protected int shouldRewindRepeatingNumbers(int nextNumber) {
if (seq.isAnySpecialCharSequence(digitSequence)) {
return 0;
}
final int nextChar = nextNumber + '0';
final int repeatingDigits = digitSequence.length() > 1 && digitSequence.charAt(digitSequence.length() - 1) == nextChar ? Cheonjiin.getRepeatingEndingDigits(digitSequence) : 0;
final int keyCharsCount = nextNumber == 0 ? 2 : language.getKeyCharacters(nextNumber).size();
if (seq.WHITESPACE_SEQUENCE.equals(digitSequence)) {
return seq.WHITESPACE_SEQUENCE.length();
}
if (repeatingDigits == 0 || keyCharsCount < 2) {
return 0;
}
@ -246,11 +252,13 @@ class ModeCheonjiin extends InputMode {
return false;
}
int number = digitSequence.isEmpty() ? Integer.MAX_VALUE : digitSequence.charAt(digitSequence.length() - 1) - '0';
if (KEY_CHARACTERS.size() > number) {
suggestions.clear();
suggestions.addAll(KEY_CHARACTERS.get(number));
return true;
if (digitSequence.equals(seq.WHITESPACE_SEQUENCE) || digitSequence.equals(seq.PUNCTUATION_SEQUENCE)) {
int number = digitSequence.isEmpty() ? Integer.MAX_VALUE : digitSequence.charAt(digitSequence.length() - 1) - '0';
if (KEY_CHARACTERS.size() > number) {
suggestions.clear();
suggestions.addAll(KEY_CHARACTERS.get(number));
return true;
}
}
return super.loadSpecialCharacters();
@ -258,7 +266,11 @@ class ModeCheonjiin extends InputMode {
protected boolean shouldDisplaySpecialCharacters() {
return digitSequence.equals(seq.PUNCTUATION_SEQUENCE) || digitSequence.equals(seq.WHITESPACE_SEQUENCE);
return
digitSequence.equals(seq.PUNCTUATION_SEQUENCE)
|| digitSequence.equals(seq.WHITESPACE_SEQUENCE)
|| digitSequence.equals(seq.CURRENCY_SEQUENCE)
|| digitSequence.equals(seq.SPECIAL_CHAR_SEQUENCE);
}
@ -324,8 +336,8 @@ class ModeCheonjiin extends InputMode {
public boolean shouldAcceptPreviousSuggestion(int nextKey, boolean hold) {
return
(hold && !digitSequence.isEmpty())
|| (digitSequence.equals(seq.WHITESPACE_SEQUENCE) && nextKey != 0)
|| (digitSequence.startsWith(seq.PUNCTUATION_SEQUENCE) && nextKey != 1);
|| (nextKey != Sequences.SPECIAL_CHAR_KEY && digitSequence.startsWith(seq.WHITESPACE_SEQUENCE))
|| (nextKey != Sequences.PUNCTUATION_KEY && digitSequence.startsWith(seq.PUNCTUATION_SEQUENCE));
}

View file

@ -176,16 +176,21 @@ public class ModeIdeograms extends ModeWords {
* the given Latin word.
*/
@Override
public void onReplaceSuggestion(@NonNull String word) {
public boolean onReplaceSuggestion(@NonNull String word) {
if (word.isEmpty() || new Text(word).isNumeric()) {
reset();
Logger.i(LOG_TAG, "Can not replace an empty or numeric word.");
return;
return false;
}
if (super.onReplaceSuggestion(word)) {
return true;
}
isFiltering = false;
stem = word;
loadSuggestions("");
return true;
}

View file

@ -65,7 +65,7 @@ public class ModePinyin extends ModeIdeograms {
// In East Asian languages, Space must accept the current word, or type a space when there is no word.
// Here, we handle the case when 0-key is Space, unlike the Space hotkey in HotkeyHandler,
// which could be a different key, assigned by the user.
if (!digitSequence.isEmpty() && !digitSequence.endsWith(seq.WHITESPACE_SEQUENCE) && nextKey == Sequences.SPECIAL_CHAR_KEY) {
if (!digitSequence.isEmpty() && !digitSequence.equals(seq.WHITESPACE_SEQUENCE) && nextKey == Sequences.SPECIAL_CHAR_KEY) {
ignoreNextSpace = true;
}

View file

@ -19,6 +19,7 @@ import io.github.sspanak.tt9.preferences.settings.SettingsStore;
import io.github.sspanak.tt9.util.Logger;
import io.github.sspanak.tt9.util.Text;
import io.github.sspanak.tt9.util.TextTools;
import io.github.sspanak.tt9.util.chars.Characters;
class ModeWords extends ModeCheonjiin {
private final String LOG_TAG = getClass().getSimpleName();
@ -68,7 +69,12 @@ class ModeWords extends ModeCheonjiin {
return false;
}
digitSequence = digitSequence.substring(0, digitSequence.length() - 1);
if (digitSequence.equals(seq.CURRENCY_SEQUENCE) || digitSequence.equals(seq.SPECIAL_CHAR_SEQUENCE)) {
digitSequence = seq.WHITESPACE_SEQUENCE;
} else {
digitSequence = digitSequence.substring(0, digitSequence.length() - 1);
}
if (digitSequence.isEmpty()) {
clearWordStem();
} else if (stem.length() > digitSequence.length()) {
@ -93,16 +99,6 @@ class ModeWords extends ModeCheonjiin {
}
@Override
protected void onNumberPress(int number) {
digitSequence = EmojiLanguage.validateEmojiSequence(seq, digitSequence, number);
if (digitSequence.equals(seq.PREFERRED_CHAR_SEQUENCE)) {
autoAcceptTimeout = 0;
}
}
@Override
public boolean changeLanguage(@Nullable Language newLanguage) {
if (newLanguage != null && newLanguage.isTranscribed()) {
@ -222,7 +218,7 @@ class ModeWords extends ModeCheonjiin {
}
try {
digitSequence = language.getDigitSequenceForWord(newStem);
digitSequence = Characters.getWhitespaces(language).contains(newStem) ? seq.WHITESPACE_SEQUENCE : language.getDigitSequenceForWord(newStem);
isStemFuzzy = !exact;
stem = newStem.toLowerCase(language.getLocale());
@ -287,7 +283,7 @@ class ModeWords extends ModeCheonjiin {
protected boolean loadPreferredChar() {
if (digitSequence.startsWith(seq.PREFERRED_CHAR_SEQUENCE)) {
if (digitSequence.equals(seq.PREFERRED_CHAR_SEQUENCE)) {
suggestions.clear();
suggestions.add(getPreferredChar());
return true;
@ -408,7 +404,9 @@ class ModeWords extends ModeCheonjiin {
// Prevent typing the preferred character when the user has scrolled the special char suggestions.
// For example, it makes more sense to allow typing "+ " with 0 + scroll + 0, instead of clearing
// the "+" and replacing it with the preferred character.
if (!stem.isEmpty() && nextKey == Sequences.SPECIAL_CHAR_KEY && digitSequence.charAt(0) == Sequences.SPECIAL_CHAR_CODE) {
boolean specialOrCurrency = digitSequence.equals(seq.SPECIAL_CHAR_SEQUENCE) || digitSequence.equals(seq.CURRENCY_SEQUENCE);
boolean isWhitespaceAndScrolled = digitSequence.equals(seq.WHITESPACE_SEQUENCE) && !stem.isEmpty();
if (nextKey == Sequences.SPECIAL_CHAR_KEY && (isWhitespaceAndScrolled || specialOrCurrency)) {
return true;
}
@ -466,6 +464,9 @@ class ModeWords extends ModeCheonjiin {
}
@Override protected int shouldRewindRepeatingNumbers(int nextNumber) { return 0; }
@NonNull
@Override
public String toString() {

View file

@ -40,6 +40,12 @@ public class Sequences {
CURRENCY_SEQUENCE = SPECIAL_CHAR_SEQUENCE + SPECIAL_CHAR_KEY;
}
public boolean startsWithEmojiSequence(String sequence) {
return
sequence != null
&& (sequence.startsWith(EMOJI_SEQUENCE) || sequence.startsWith(CUSTOM_EMOJI_SEQUENCE));
}
public boolean isAnySpecialCharSequence(String sequence) {
if (sequence == null) {
return false;

View file

@ -109,10 +109,10 @@ public class SoftKeyNumber2to9 extends SoftKeyNumber {
*/
private String abbreviateCharList(String chars, String abbreviationSign, Locale locale, boolean isUppercase) {
String firstLetter = chars.substring(0, 1);
firstLetter = TextTools.isCombining(firstLetter) ? Characters.PLACEHOLDER + firstLetter : firstLetter;
firstLetter = TextTools.isCombining(firstLetter) ? Characters.COMBINING_BASE + firstLetter : firstLetter;
String lastLetter = chars.substring(chars.length() - 1);
lastLetter = TextTools.isCombining(lastLetter) ? Characters.PLACEHOLDER + lastLetter : lastLetter;
lastLetter = TextTools.isCombining(lastLetter) ? Characters.COMBINING_BASE + lastLetter : lastLetter;
String list = firstLetter + abbreviationSign + lastLetter;
return isUppercase ? list.toUpperCase(locale) : list;

View file

@ -27,8 +27,8 @@ import io.github.sspanak.tt9.util.TextTools;
import io.github.sspanak.tt9.util.chars.Characters;
public class SuggestionsBar {
public static final String SHOW_SPECIAL_CHARS_SUGGESTION = "(@#*…)";
public static final String SHOW_CURRENCIES_SUGGESTION = "($€£…)";
public static final String SHOW_SPECIAL_CHARS_SUGGESTION = "#%…";
public static final String SHOW_CURRENCIES_SUGGESTION = "$€…";
private final String SHOW_MORE_SUGGESTION = "(...)";
private final String STEM_SUFFIX = "… +";
@ -165,7 +165,7 @@ public class SuggestionsBar {
// "..." prefix
int startIndex = 0;
String[] prefixes = {STEM_VARIATION_PREFIX, STEM_PUNCTUATION_VARIATION_PREFIX, Characters.PLACEHOLDER};
String[] prefixes = {STEM_VARIATION_PREFIX, STEM_PUNCTUATION_VARIATION_PREFIX, Characters.COMBINING_BASE};
for (String prefix : prefixes) {
int prefixIndex = suggestion.indexOf(prefix) + 1;
if (prefixIndex < endIndex) { // do not match the prefix chars when they are part of STEM_SUFFIX
@ -324,7 +324,7 @@ public class SuggestionsBar {
private String formatUnreadableSuggestion(String suggestion) {
if (TextTools.isCombining(suggestion)) {
return Characters.PLACEHOLDER + suggestion;
return Characters.COMBINING_BASE + suggestion;
}
return switch (suggestion) {

View file

@ -10,9 +10,10 @@ import io.github.sspanak.tt9.languages.Language;
import io.github.sspanak.tt9.languages.LanguageKind;
public class Characters extends Emoji {
public static final String PLACEHOLDER = "";
public static final String COMBINING_BASE = "";
public static final String IDEOGRAPHIC_SPACE = " ";
public static final String TAB = "";
public static final String PLACEHOLDER = "\u200A";
public static final String TAB = "Tab";
public static final ArrayList<String> Currency = new ArrayList<>(Arrays.asList(