1
0
Fork 0

word stem is now displayed in the suggestion list

This commit is contained in:
sspanak 2024-08-29 19:18:11 +03:00 committed by Dimo Karaivanov
parent 81698c72da
commit 5f8280b545
10 changed files with 90 additions and 19 deletions

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools" <manifest xmlns:tools="http://schemas.android.com/tools"
android:versionCode="643" android:versionCode="659"
android:versionName="37.0" android:versionName="37.16"
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <!-- allows displaying notifications on Android >= 13 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <!-- allows displaying notifications on Android >= 13 -->

View file

@ -176,7 +176,7 @@ abstract public class CommandHandler extends TextEditingHandler {
} }
} }
suggestionOps.set(mInputMode.getSuggestions(), currentSuggestionIndex); suggestionOps.set(mInputMode.getSuggestions(), currentSuggestionIndex, mInputMode.containsGeneratedSuggestions());
textField.setComposingText(suggestionOps.getCurrent()); textField.setComposingText(suggestionOps.getCurrent());
} }

View file

@ -55,7 +55,7 @@ public class TraditionalT9 extends MainViewHandler {
initTray(); initTray();
setDarkTheme(); setDarkTheme();
statusBar.setText(mInputMode); statusBar.setText(mInputMode);
suggestionOps.set(mInputMode.getSuggestions()); suggestionOps.set(mInputMode.getSuggestions(), mInputMode.containsGeneratedSuggestions());
return mainView.getView(); return mainView.getView();
} }

View file

@ -352,7 +352,7 @@ public abstract class TypingHandler extends KeyPadHandler {
} }
// display the word suggestions // display the word suggestions
suggestionOps.set(mInputMode.getSuggestions()); suggestionOps.set(mInputMode.getSuggestions(), mInputMode.containsGeneratedSuggestions());
// In case we are here, because the language was changed, and there were words for the old language, // In case we are here, because the language was changed, and there were words for the old language,
// but there are no words for the new language, we'll get only generated suggestions, consisting // but there are no words for the new language, we'll get only generated suggestions, consisting

View file

@ -49,14 +49,17 @@ public class SuggestionOps {
textField.finishComposingText(); textField.finishComposingText();
} }
public void set(ArrayList<String> suggestions) { public void set(ArrayList<String> suggestions) {
suggestionBar.setSuggestions(suggestions, 0); suggestionBar.setSuggestions(suggestions, 0, false);
}
public void set(ArrayList<String> suggestions, boolean containsGenerated) {
suggestionBar.setSuggestions(suggestions, 0, containsGenerated);
} }
public void set(ArrayList<String> suggestions, int selectIndex) { public void set(ArrayList<String> suggestions, int selectIndex, boolean containsGenerated) {
suggestionBar.setSuggestions(suggestions, selectIndex); suggestionBar.setSuggestions(suggestions, selectIndex, containsGenerated);
} }

View file

@ -85,6 +85,7 @@ abstract public class InputMode {
// Utility // Utility
abstract public int getId(); abstract public int getId();
public boolean containsGeneratedSuggestions() { return false; }
public int getSequenceLength() { return digitSequence.length(); } // The number of key presses for the current word. public int getSequenceLength() { return digitSequence.length(); } // The number of key presses for the current word.
public int getAutoAcceptTimeout() { public int getAutoAcceptTimeout() {
return autoAcceptTimeout; return autoAcceptTimeout;

View file

@ -243,6 +243,11 @@ public class ModePredictive extends InputMode {
} }
@Override
public boolean containsGeneratedSuggestions() {
return predictions.containsGeneratedWords();
}
/** /**
* loadSuggestions * loadSuggestions
* Loads the possible list of suggestions for the current digitSequence. "currentWord" is used * Loads the possible list of suggestions for the current digitSequence. "currentWord" is used

View file

@ -20,6 +20,7 @@ public class Predictions {
// data // data
private boolean areThereDbWords = false; private boolean areThereDbWords = false;
private boolean containsGeneratedWords = false;
private ArrayList<String> words = new ArrayList<>(); private ArrayList<String> words = new ArrayList<>();
@ -53,6 +54,10 @@ public class Predictions {
return this; return this;
} }
public boolean containsGeneratedWords() {
return containsGeneratedWords;
}
public ArrayList<String> getList() { public ArrayList<String> getList() {
return words; return words;
} }
@ -93,6 +98,8 @@ public class Predictions {
* sequence or loads the static ones. * sequence or loads the static ones.
*/ */
public void load() { public void load() {
containsGeneratedWords = false;
if (digitSequence == null || digitSequence.isEmpty()) { if (digitSequence == null || digitSequence.isEmpty()) {
words.clear(); words.clear();
onWordsChanged.run(); onWordsChanged.run();
@ -194,6 +201,7 @@ public class Predictions {
generatedWords.add(baseWord + digitSequence.charAt(digitSequence.length() - 1)); generatedWords.add(baseWord + digitSequence.charAt(digitSequence.length() - 1));
} }
containsGeneratedWords = true;
return generatedWords; return generatedWords;
} }
@ -235,6 +243,7 @@ public class Predictions {
} }
} }
containsGeneratedWords = true;
return complementedWords; return complementedWords;
} }
@ -273,6 +282,7 @@ public class Predictions {
} }
} }
containsGeneratedWords = !variations.isEmpty();
return variations; return variations;
} }
} }

View file

@ -25,6 +25,11 @@ import io.github.sspanak.tt9.ui.main.ResizableMainView;
import io.github.sspanak.tt9.util.Characters; import io.github.sspanak.tt9.util.Characters;
public class SuggestionsBar { public class SuggestionsBar {
private final String STEM_SUFFIX = "… +";
private final String STEM_VARIATION_PREFIX = "";
private final String STEM_PUNCTUATION_VARIATION_PREFIX = " ";
@NonNull private String stem = "";
private double lastClickTime = 0; private double lastClickTime = 0;
private final List<String> suggestions = new ArrayList<>(); private final List<String> suggestions = new ArrayList<>();
protected int selectedIndex = 0; protected int selectedIndex = 0;
@ -116,25 +121,72 @@ public class SuggestionsBar {
return ""; return "";
} }
if (suggestions.get(id).endsWith(STEM_SUFFIX)) {
return stem;
} else if (suggestions.get(id).startsWith(STEM_VARIATION_PREFIX)) {
return stem + suggestions.get(id).substring(STEM_VARIATION_PREFIX.length());
} else if (suggestions.get(id).startsWith(STEM_PUNCTUATION_VARIATION_PREFIX)) {
return stem + suggestions.get(id).substring(STEM_PUNCTUATION_VARIATION_PREFIX.length());
}
return suggestions.get(id).equals(Characters.getNewLine()) ? "\n" : suggestions.get(id); return suggestions.get(id).equals(Characters.getNewLine()) ? "\n" : suggestions.get(id);
} }
public void setSuggestions(List<String> newSuggestions, int initialSel) { public void setSuggestions(List<String> newSuggestions, int initialSel, boolean containsGenerated) {
ecoSetBackground(newSuggestions); ecoSetBackground(newSuggestions);
suggestions.clear(); suggestions.clear();
selectedIndex = 0; selectedIndex = newSuggestions == null || newSuggestions.isEmpty() ? 0 : Math.max(initialSel, 0);
if (newSuggestions != null) { setStem(newSuggestions, containsGenerated);
for (String suggestion : newSuggestions) { addAllSuggestions(newSuggestions);
// make the new line better readable setSuggestionsOnScreen();
suggestions.add(suggestion.equals("\n") ? Characters.getNewLine() : suggestion); }
}
selectedIndex = Math.max(initialSel, 0);
private void setStem(List<String> newSuggestions, boolean containsGenerated) {
if (newSuggestions == null || newSuggestions.isEmpty()) {
stem = "";
return;
} }
setSuggestionsOnScreen(); stem = containsGenerated ? newSuggestions.get(0).substring(0, newSuggestions.get(0).length() - 1) : "";
// Do not modify single letter + punctuation, such as "j'" or "l'". They look better as they are.
stem = (stem.length() == 1 && newSuggestions.get(0).length() == 2 && !Character.isAlphabetic(newSuggestions.get(0).charAt(1))) ? "" : stem;
if (!stem.isEmpty() && !newSuggestions.contains(stem)) {
suggestions.add(stem + STEM_SUFFIX);
selectedIndex++;
}
}
private void addAllSuggestions(List<String> newSuggestions) {
if (newSuggestions != null) {
for (String suggestion : newSuggestions) {
addSuggestion(suggestion);
}
}
}
private void addSuggestion(@NonNull String suggestion) {
// shorten the stem variations
if (!stem.isEmpty() && suggestion.length() == stem.length() + 1 && suggestion.toLowerCase().startsWith(stem.toLowerCase())) {
String trimmedSuggestion = suggestion.substring(stem.length());
trimmedSuggestion = Character.isAlphabetic(trimmedSuggestion.charAt(0)) ? STEM_VARIATION_PREFIX + trimmedSuggestion : STEM_PUNCTUATION_VARIATION_PREFIX + trimmedSuggestion;
suggestions.add(trimmedSuggestion);
}
// make the new line better readable
else if (suggestion.equals("\n")) {
suggestions.add(Characters.getNewLine());
}
// or add any other suggestion as is
else {
suggestions.add(suggestion);
}
} }

View file

@ -42,7 +42,7 @@ _Predictive mode only._
- **Single press**: Filter the suggestion list, leaving out only the ones that start with the current word. It doesn't matter if it is a complete word or not. For example, type "remin" and press Filter. It will leave out all words starting with "remin": "remin" itself, "remind", "reminds", "reminded", "reminding", and so on. - **Single press**: Filter the suggestion list, leaving out only the ones that start with the current word. It doesn't matter if it is a complete word or not. For example, type "remin" and press Filter. It will leave out all words starting with "remin": "remin" itself, "remind", "reminds", "reminded", "reminding", and so on.
- **Double press**: Expand the filter to the full suggestion. For example, type "remin" and press Filter twice. It will first filter by "remin", then expand the filter to "remind". You can keep expanding the filter until you get to the longest dictionary word. - **Double press**: Expand the filter to the full suggestion. For example, type "remin" and press Filter twice. It will first filter by "remin", then expand the filter to "remind". You can keep expanding the filter until you get to the longest dictionary word.
Filtering can also be used to type unknown words. Let's say you want to type "Anakin", which is not in the dictionary. Start with "A", then press Filter to hide "B" and "C". Now press 6-key. Since the filter is on, in addition to the real dictionary words, it will provide all possible combinations for 6: "Am", "An", "Ao". Select "An" and press Filter to confirm your selection. Now pressing the 2-key, will provide "Ana", "Anb", and "Anc". Keep going, until you get "Anakin". Filtering is also useful for typing unknown words. Let's say you want to type "Anakin", which is not in the dictionary. Start with "A", then press Filter to hide "B" and "C". Now press 6-key. Since the filter is on, in addition to the real dictionary words, it will provide all possible combinations for 1+6: "A..." + "m", "n", "o". Select "n" and press Filter to confirm your selection and produce "An". Now pressing the 2-key, will provide "An..." + "a", "b", and "c". Select "a", and keep going, until you get "Anakin".
When filtering is enabled, the base text will become bold and italicized. When filtering is enabled, the base text will become bold and italicized.