Restore Add word (#73)
* adding words to the dictionary is possible again * removed some unused code * updated Readme files * special key handlers now validate the input mode themselves * improved language validation and error handling here and there
This commit is contained in:
parent
78b6681812
commit
8d85215444
18 changed files with 195 additions and 159 deletions
|
|
@ -1,13 +1,13 @@
|
|||
# Traditional T9
|
||||
TT9 is an IME (Input Method Editor) for Android devices with hardware keypad. It supports multiple languages and predictive text typing. _NOTE: TT9 is not usable on touchscreen-only devices._
|
||||
|
||||
This is a clone of the [original project](https://github.com/Clam-/TraditionalT9) by Clam-.
|
||||
This is an updated version of the [original project](https://github.com/Clam-/TraditionalT9) by Clam-.
|
||||
|
||||
## Building
|
||||
The recommended way of building is using Android Studio. As the of time of writing this, the current version is Android Studio Chipmunk | 2021.2.1 Patch 1.
|
||||
The recommended way of building is using Android Studio. As the of time of writing this, the current version is: Android Studio Dolphin | 2021.3.1.
|
||||
|
||||
### Building a Debug .apk
|
||||
If you have not configure Android Studio yet, follow [the official manual](https://developer.android.com/training/basics/firstapp), then follow the simple steps below to get the project running.
|
||||
If you have not configured Android Studio yet, follow [the official manual](https://developer.android.com/training/basics/firstapp), then follow the simple steps below to get the project running.
|
||||
|
||||
- _Import the project in Android Studio._
|
||||
- _Prevent the "Default Activity not found" issue._ The app does not have a default view or a launcher icon. For this reason, you must configure Android Studio not to launch anything after installing, otherwise it will fail with "Default Activity not found" or a similar message. To do so:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Traditional T9
|
||||
TT9 is an IME (Input Method Editor) for Android devices with hardware keypad. It supports multiple languages and predictive text typing. _NOTE: TT9 is not usable on touchscreen-only devices._
|
||||
|
||||
Source code and documentation are available on Github: [https://github.com/sspanak/tt9](https://github.com/sspanak/tt9).
|
||||
All Source code and documentation are available on Github: [https://github.com/sspanak/tt9](https://github.com/sspanak/tt9).
|
||||
|
||||
## Initial Setup
|
||||
In order to use Traditional T9, you need to enable it as an Android keyboard. To do so:
|
||||
|
|
@ -14,25 +14,20 @@ _The actual menu names may vary depending on your Android version and phone._
|
|||
### Enabling Predictive Mode
|
||||
With the default settings, it is only possible to type in 123 and ABC modes. In order to enable the Predictive mode, there are additional steps:
|
||||
|
||||
- Open the [TT9 Configuration screen](#configuration-options).
|
||||
- Open the [Configuration screen](#configuration-options).
|
||||
- Select the desired languages.
|
||||
- Load the dictionaries.
|
||||
|
||||
_If you don't do the above, nothing will happen when you try to type in Predictive mode._
|
||||
_If you don't do the above, there will be no suggestions when typing in Predictive mode._
|
||||
|
||||
## Hotkeys
|
||||
|
||||
#### D-pad Up (↑):
|
||||
Select previous word suggestion.
|
||||
|
||||
#### D-pad Down (↓):
|
||||
Select next word suggestion.
|
||||
|
||||
#### Left Soft Key:
|
||||
Open Traditional T9 Configuration screen.
|
||||
|
||||
#### Right Soft Key:
|
||||
Backspace.
|
||||
|
||||
#### 0 key
|
||||
- In 123 mode: type "0" or hold it to type "+".
|
||||
- In ABC mode: type secondary punctuation or hold to type "0".
|
||||
|
|
@ -44,13 +39,13 @@ Backspace.
|
|||
|
||||
#### Text Mode Key (Hash/Pound/#):
|
||||
- **Short press:** Cycle input modes (abc → ABC → Predictive → 123)
|
||||
- **Short press while typing:** Change between UPPERCASE and lowercase.
|
||||
- **Short press while typing:** Change between UPPERCASE/lowercase.
|
||||
- **Long press:** Select the next language.
|
||||
- **Number-only fields:** Type a "#". Changing the mode is not possible in such fields.
|
||||
|
||||
#### Other Actions Key (Star/✱):
|
||||
- **Short press:** Add a word to the dictionary.
|
||||
- **Long press:** Open Traditional T9 Preferences screen.
|
||||
- **Short press:** Add a new word to the dictionary.
|
||||
- **Long press:** Open the Configration screen.
|
||||
|
||||
#### Backspace Key (Back/↩):
|
||||
- Just deletes text.
|
||||
|
|
@ -60,6 +55,15 @@ Backspace.
|
|||
- **Short Press when there is text:** Some applications, most notably Firefox and Spotify, take full control of the "Back" key. This means, it may function as the application authors intended, instead of as backspace. In such cases, you could use the on-screen backspace instead. Unfortunately, nothing else could be done, because this is a restriction posed by Android.
|
||||
- **Long Press**: Whatever the system default action is (i.e. show running applications list).
|
||||
|
||||
## On-screen soft keys
|
||||
All functionality is available using the keypad, but for convenience, on touchscreen phones or the ones with customizable function keys, you could also use the on-screen soft keys.
|
||||
|
||||
#### Left Soft Key:
|
||||
Open the [Configuration screen](#configuration-options).
|
||||
|
||||
#### Right Soft Key:
|
||||
Backspace.
|
||||
|
||||
## Configuration Options
|
||||
On the Configuration screen, you can choose your preferred languages, load a dictionary for Predictive mode or view this manual.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,17 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingHorizontal="6dp"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<EditText
|
||||
android:id="@+id/add_word_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="4dp"
|
||||
android:inputType="text"
|
||||
android:privateImeOptions="io.github.sspanak.tt9.addword=true" >
|
||||
android:privateImeOptions="io.github.sspanak.tt9.addword=true"
|
||||
android:importantForAutofill="no">
|
||||
|
||||
<requestFocus />
|
||||
</EditText>
|
||||
|
|
@ -22,18 +25,20 @@
|
|||
android:id="@+id/add_word_add"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:onClick="addWordButton"
|
||||
android:minWidth="48dp"
|
||||
android:onClick="addWord"
|
||||
android:text="@string/add_word_add" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_word_cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:onClick="cancelButton"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:minWidth="48dp"
|
||||
android:onClick="cancelAddingWord"
|
||||
android:text="@android:string/cancel" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
|||
|
|
@ -2,13 +2,12 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_settings">Настройки на Traditional T9</string>
|
||||
<string name="close">Затвори</string>
|
||||
<string name="error_unexpected">Възникна неочаквана грешка.</string>
|
||||
|
||||
<string name="add_word_add">Добави</string>
|
||||
<string name="add_word_blank">Не може да се въведе празна дума.</string>
|
||||
<string name="add_word_badchar">Не може да се въведе дума с непозволени символи за %1$s (%2$s).</string>
|
||||
<string name="add_word_exist1">(%1$s) е вече речника.</string>
|
||||
<string name="add_word_exist2">(%1$s) е вече в речника за %2$s.</string>
|
||||
<string name="add_word_only_in_predictive_mode">Може да добавяте думи само в подсказващ режим.</string>
|
||||
<string name="add_word_exist">Думата „%1$s“ е вече речника.</string>
|
||||
<string name="add_word_invalid_language">За да добавите нова дума, първо изберете език.</string>
|
||||
<string name="add_word_title">Добавяне на дума</string>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
<resources>
|
||||
<string name="app_settings">Traditional T9 Einstellungen</string>
|
||||
<string name="close">Schließen</string>
|
||||
<string name="error_unexpected">Unerwarteter Fehler aufgetreten.</string>
|
||||
|
||||
<string name="add_word_add">Hinzufügen</string>
|
||||
<string name="add_word_blank">Leeres Wort nicht hinzugefügt.</string>
|
||||
<string name="add_word_badchar">Wort mit nicht zuordbarem Buchstaben für %1$s (%2$s) kann nicht hinzugefügt werden.</string>
|
||||
<string name="add_word_exist1">Das Wort (%1$s) ist bereits in der DB.</string>
|
||||
<string name="add_word_exist2">Das Wort (%1$s) ist bereits für %2$s in der DB.</string>
|
||||
<string name="add_word_exist">Das Wort \"%1$s\" ist bereits in Wörterbuch.</string>
|
||||
<string name="add_word_title">Wort hinzufügen</string>
|
||||
|
||||
<string name="pref_help">"Hilfe anzeigen</string>
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
<resources>
|
||||
<string name="app_settings">Configuration Traditional T9 </string>
|
||||
<string name="close">Fermer</string>
|
||||
<string name="error_unexpected">Une erreur inattendue s\'est produite.</string>
|
||||
|
||||
<string name="add_word_add">Ajouter</string>
|
||||
<string name="add_word_blank">Mot vide non ajouté.</string>
|
||||
<string name="add_word_badchar">Impossible d\'ajouter un mot avec des caractères inexistants pour %1$s (%2$s).</string>
|
||||
<string name="add_word_exist1">Le mot (%1$s) est déjà dans la BD.</string>
|
||||
<string name="add_word_exist2">Le mot (%1$s) est déjà dans la BD pour %2$s.</string>
|
||||
<string name="add_word_exist">Le mot «%1$s» est déjà dans le dictionnaire.</string>
|
||||
<string name="add_word_title">Ajouter un mot</string>
|
||||
|
||||
<string name="pref_help">"Afficher l\'aide</string>
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
<resources>
|
||||
<string name="app_settings">Traditional T9 Impostazioni</string>
|
||||
<string name="close">Chiudi</string>
|
||||
<string name="error_unexpected">Si è verificato un errore imprevisto.</string>
|
||||
|
||||
<string name="add_word_add">Aggiungere</string>
|
||||
<string name="add_word_blank">Nessuna parola da aggiungere.</string>
|
||||
<string name="add_word_badchar">Impossibile aggiungere parola con caratteri inesistenti per %1$s (%2$s).</string>
|
||||
<string name="add_word_exist1">Parola (%1$s) già nel database.</string>
|
||||
<string name="add_word_exist2">Parola (%1$s) già nel database per %2$s.</string>
|
||||
<string name="add_word_exist">Parola “%1$s” già nel dizionario.</string>
|
||||
<string name="add_word_title">Aggiungi parola</string>
|
||||
|
||||
<string name="pref_help">"Mostra aiuto</string>
|
||||
|
|
|
|||
|
|
@ -2,14 +2,13 @@
|
|||
<resources>
|
||||
<string name="app_settings">Traditional T9 настройки</string>
|
||||
<string name="close">Закрыть</string>
|
||||
<string name="error_unexpected">Произошла непредвиденная ошибка.</string>
|
||||
|
||||
<string name="add_word_add">Добавить</string>
|
||||
<string name="add_word_badchar">Невозможно добавить слово с таким символом %1$s (%2$s).</string>
|
||||
<string name="add_word_blank">Невозможно добавить слово.</string>
|
||||
<string name="add_word_exist1">Слово (%1$s) уже есть в словаре.</string>
|
||||
<string name="add_word_exist2">Слово (%1$s) уже есть в словаре %2$s.</string>
|
||||
<string name="add_word_exist">Слово «%1$s» уже есть в словаре.</string>
|
||||
<string name="add_word_invalid_language">Чтобы добавить новое слово, сначала выберите язык.</string>
|
||||
<string name="add_word_only_in_predictive_mode">Словарь успешно очищен.</string>
|
||||
<string name="add_word_title">Добавить слово</string>
|
||||
|
||||
<string name="pref_help">О программе</string>
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
<resources>
|
||||
<string name="app_settings">Налаштування Traditional T9</string>
|
||||
<string name="close">Закрити</string>
|
||||
<string name="error_unexpected">Сталася неочікувана помилка.</string>
|
||||
|
||||
<string name="add_word_add">Додати</string>
|
||||
<string name="add_word_badchar">Неможливо додати слово з таким символом %1$s (%2$s).</string>
|
||||
<string name="add_word_blank">Неможливо додати слово.</string>
|
||||
<string name="add_word_exist1">Слово (%1$s) вже є в словнику.</string>
|
||||
<string name="add_word_exist2">Слово (%1$s) вже є в словнику %2$s.</string>
|
||||
<string name="add_word_exist">Слово «%1$s» вже є в словнику.</string>
|
||||
<string name="add_word_title">Додати слово</string>
|
||||
|
||||
<string name="pref_help">Про програму</string>
|
||||
|
|
|
|||
|
|
@ -3,16 +3,15 @@
|
|||
<string translatable="false" name="help_url">https://github.com/sspanak/tt9/blob/master/docs/user-manual.md</string>
|
||||
<string name="app_name" translatable="false">Traditional T9</string>
|
||||
<string name="app_settings">Traditional T9 Settings</string>
|
||||
<string name="soft_key_mid" translatable="false">OK</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="error_unexpected">Unexpected error occurred.</string>
|
||||
<string name="soft_key_mid" translatable="false">OK</string>
|
||||
|
||||
<string name="add_word_add">Add</string>
|
||||
<string name="add_word_blank">Blank word not added.</string>
|
||||
<string name="add_word_badchar">Cannot add word with unmappable character for %1$s (%2$s).</string>
|
||||
<string name="add_word_exist1">Word (%1$s) already in DB.</string>
|
||||
<string name="add_word_exist2">Word (%1$s) already in DB for %2$s.</string>
|
||||
<string name="add_word_exist">Word \"%1$s\" already in the dictionary.</string>
|
||||
<string name="add_word_invalid_language">Cannot insert a word when no language is selected.</string>
|
||||
<string name="add_word_only_in_predictive_mode">You can add new words in Predictive mode only.</string>
|
||||
<string name="add_word_title">Add Word</string>
|
||||
|
||||
<string name="pref_help">Show Help</string>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package io.github.sspanak.tt9.db;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteConstraintException;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
|
|
@ -10,12 +11,12 @@ import androidx.room.Room;
|
|||
import androidx.room.RoomDatabase;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
import java.io.NotActiveException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.languages.InvalidLanguageException;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
|
||||
public class DictionaryDb {
|
||||
private static T9RoomDb dbInstance;
|
||||
|
|
@ -91,28 +92,50 @@ public class DictionaryDb {
|
|||
}
|
||||
|
||||
|
||||
public static void insertWord(Context context, String word, int languageId) throws InvalidLanguageException, InsertBlankWordException, NotActiveException {
|
||||
if (languageId <= 0) {
|
||||
throw new InvalidLanguageException("Cannot insert a word for an invalid language with ID: '" + languageId + "'");
|
||||
public static void insertWord(Context context, Handler handler, Language language, String word) throws Exception {
|
||||
if (language == null) {
|
||||
throw new InvalidLanguageException();
|
||||
}
|
||||
|
||||
if (word == null || word.length() == 0) {
|
||||
throw new InsertBlankWordException();
|
||||
}
|
||||
|
||||
// @todo: insert async with max priority for this sequence.
|
||||
throw new NotActiveException("Adding new words is disabled in this version. Please, check for updates.");
|
||||
Word dbWord = new Word();
|
||||
dbWord.langId = language.getId();
|
||||
dbWord.sequence = language.getDigitSequenceForWord(word);
|
||||
dbWord.word = word.toLowerCase(language.getLocale());
|
||||
dbWord.frequency = 1;
|
||||
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
getInstance(context).wordsDao().insert(dbWord);
|
||||
getInstance(context).wordsDao().incrementFrequency(dbWord.langId, dbWord.word, dbWord.sequence);
|
||||
handler.sendEmptyMessage(0);
|
||||
} catch (SQLiteConstraintException e) {
|
||||
String msg = "Constraint violation when inserting a word: '" + dbWord.word + "' / sequence: '" + dbWord.sequence + "', for language: " + dbWord.langId;
|
||||
Logger.e("tt9/insertWord", msg);
|
||||
handler.sendEmptyMessage(1);
|
||||
} catch (Exception e) {
|
||||
String msg = "Failed inserting word: '" + dbWord.word + "' / sequence: '" + dbWord.sequence + "', for language: " + dbWord.langId;
|
||||
Logger.e("tt9/insertWord", msg);
|
||||
handler.sendEmptyMessage(2);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
|
||||
public static void insertWordsSync(Context context, List<Word> words) {
|
||||
getInstance(context).wordsDao().insertWords(words);
|
||||
getInstance(context).wordsDao().insertMany(words);
|
||||
}
|
||||
|
||||
|
||||
public static void incrementWordFrequency(Context context, int langId, String word, String sequence) throws Exception {
|
||||
if (langId <= 0) {
|
||||
throw new InvalidLanguageException("Cannot increment word frequency for an invalid language: '" + langId + "'");
|
||||
public static void incrementWordFrequency(Context context, Language language, String word, String sequence) throws Exception {
|
||||
if (language == null) {
|
||||
throw new InvalidLanguageException();
|
||||
}
|
||||
|
||||
// If both are empty, it is the same as changing the frequency of: "", which is simply a no-op.
|
||||
|
|
@ -130,7 +153,7 @@ public class DictionaryDb {
|
|||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
getInstance(context).wordsDao().incrementFrequency(langId, word, sequence);
|
||||
getInstance(context).wordsDao().incrementFrequency(language.getId(), word, sequence);
|
||||
} catch (Exception e) {
|
||||
Logger.e(
|
||||
DictionaryDb.class.getName(),
|
||||
|
|
@ -142,7 +165,7 @@ public class DictionaryDb {
|
|||
}
|
||||
|
||||
|
||||
public static void getSuggestions(Context context, Handler handler, int langId, String sequence, int minimumWords, int maximumWords) {
|
||||
public static void getSuggestions(Context context, Handler handler, Language language, String sequence, int minimumWords, int maximumWords) {
|
||||
final int minWords = Math.max(minimumWords, 0);
|
||||
final int maxWords = Math.max(maximumWords, minimumWords);
|
||||
|
||||
|
|
@ -150,12 +173,19 @@ public class DictionaryDb {
|
|||
@Override
|
||||
public void run() {
|
||||
if (sequence == null || sequence.length() == 0) {
|
||||
Logger.w("tt9/getSuggestions", "Attempting to get suggestions for an empty sequence.");
|
||||
sendSuggestions(handler, new ArrayList<>());
|
||||
return;
|
||||
}
|
||||
|
||||
if (language == null) {
|
||||
Logger.w("tt9/getSuggestions", "Attempting to get suggestions for NULL language.");
|
||||
sendSuggestions(handler, new ArrayList<>());
|
||||
return;
|
||||
}
|
||||
|
||||
// get exact sequence matches, for example: "9422" -> "what"
|
||||
List<Word> exactMatches = getInstance(context).wordsDao().getMany(langId, sequence, maxWords);
|
||||
List<Word> exactMatches = getInstance(context).wordsDao().getMany(language.getId(), sequence, maxWords);
|
||||
Logger.d("getWords", "Exact matches: " + exactMatches.size());
|
||||
|
||||
ArrayList<String> suggestions = new ArrayList<>();
|
||||
|
|
@ -168,7 +198,7 @@ public class DictionaryDb {
|
|||
// for example: "rol" => "roll", "roller", "rolling", ...
|
||||
if (exactMatches.size() < minWords && sequence.length() >= 2) {
|
||||
int extraWordsNeeded = minWords - exactMatches.size();
|
||||
List<Word> extraWords = getInstance(context).wordsDao().getFuzzy(langId, sequence, extraWordsNeeded);
|
||||
List<Word> extraWords = getInstance(context).wordsDao().getFuzzy(language.getId(), sequence, extraWordsNeeded);
|
||||
Logger.d("getWords", "Fuzzy matches: " + extraWords.size());
|
||||
|
||||
for (Word word : extraWords) {
|
||||
|
|
|
|||
|
|
@ -27,8 +27,11 @@ interface WordsDao {
|
|||
)
|
||||
List<Word> getFuzzy(int langId, String sequence, int limit);
|
||||
|
||||
@Insert
|
||||
void insert(Word word);
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
void insertWords(List<Word> words);
|
||||
void insertMany(List<Word> words);
|
||||
|
||||
@Query(
|
||||
"UPDATE words " +
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
package io.github.sspanak.tt9.ime;
|
||||
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.ExtractedText;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
class InputFieldHelper {
|
||||
|
|
@ -157,23 +157,12 @@ class InputFieldHelper {
|
|||
|
||||
|
||||
public static String getSurroundingWord(InputConnection currentInputConnection) {
|
||||
CharSequence before = currentInputConnection.getTextBeforeCursor(50, 0);
|
||||
CharSequence after = currentInputConnection.getTextAfterCursor(50, 0);
|
||||
int bounds = -1;
|
||||
if (!TextUtils.isEmpty(before)) {
|
||||
bounds = before.length() -1;
|
||||
while (bounds > 0 && !Character.isWhitespace(before.charAt(bounds))) {
|
||||
bounds--;
|
||||
}
|
||||
before = before.subSequence(bounds, before.length());
|
||||
}
|
||||
if (!TextUtils.isEmpty(after)) {
|
||||
bounds = 0;
|
||||
while (bounds < after.length() && !Character.isWhitespace(after.charAt(bounds))) {
|
||||
bounds++;
|
||||
}
|
||||
after = after.subSequence(0, bounds);
|
||||
}
|
||||
return before.toString().trim() + after.toString().trim();
|
||||
String before = (String) currentInputConnection.getTextBeforeCursor(50, 0);
|
||||
String after = (String) currentInputConnection.getTextAfterCursor(50, 0);
|
||||
|
||||
Matcher beforeMatch = Pattern.compile("(\\w+)$").matcher(before);
|
||||
Matcher afterMatch = Pattern.compile("^(\\w+)").matcher(after);
|
||||
|
||||
return (beforeMatch.find() ? beforeMatch.group(1) : "") + (afterMatch.find() ? afterMatch.group(1) : "");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import android.view.KeyEvent;
|
|||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
import java.io.NotActiveException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
|
@ -16,8 +15,6 @@ import java.util.List;
|
|||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.db.DictionaryDb;
|
||||
import io.github.sspanak.tt9.db.InsertBlankWordException;
|
||||
import io.github.sspanak.tt9.languages.InvalidLanguageException;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.languages.Punctuation;
|
||||
|
|
@ -75,6 +72,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
}
|
||||
|
||||
loadPreferences();
|
||||
prefs.clearLastWord();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -98,7 +96,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
determineAllowedInputModes(inputField);
|
||||
determineAllowedTextCases();
|
||||
|
||||
// @todo: handle word adding
|
||||
restoreAddedWordIfAny();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -106,8 +104,6 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
predictionSequence = "";
|
||||
clearSuggestions();
|
||||
|
||||
// @todo: clear previous word
|
||||
|
||||
hideStatusIcon();
|
||||
hideWindow();
|
||||
|
||||
|
|
@ -228,6 +224,10 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
|
||||
protected boolean onKeyInputMode(boolean hold) {
|
||||
if (mEditing == EDITING_DIALER) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hold) {
|
||||
nextLang();
|
||||
} else {
|
||||
|
|
@ -239,6 +239,10 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
|
||||
protected boolean onKeyOtherAction(boolean hold) {
|
||||
if (mEditing == EDITING_NOSHOW || mEditing == EDITING_DIALER) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hold) {
|
||||
UI.showPreferencesScreen(this);
|
||||
} else {
|
||||
|
|
@ -358,7 +362,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
DictionaryDb.getSuggestions(
|
||||
this,
|
||||
handleSuggestions,
|
||||
mLanguage.getId(),
|
||||
mLanguage,
|
||||
predictionSequence,
|
||||
prefs.getSuggestionsMin(),
|
||||
prefs.getSuggestionsMax()
|
||||
|
|
@ -402,7 +406,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
try {
|
||||
String sequence = mLanguage.getDigitSequenceForWord(currentWord);
|
||||
DictionaryDb.incrementWordFrequency(this, mLanguage.getId(), currentWord, sequence);
|
||||
DictionaryDb.incrementWordFrequency(this, mLanguage, currentWord, sequence);
|
||||
} catch (Exception e) {
|
||||
Logger.e(getClass().getName(), "Failed incrementing priority of word: '" + currentWord + "'. " + e.getMessage());
|
||||
}
|
||||
|
|
@ -556,50 +560,35 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
|
||||
private void showAddWord() {
|
||||
if (mInputMode != MODE_PREDICTIVE) {
|
||||
UI.toastLong(this, R.string.add_word_only_in_predictive_mode);
|
||||
return;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// @todo: remove this try..catch in #55 and display the dialog
|
||||
try {
|
||||
DictionaryDb.insertWord(this, "a", mLanguage.getId());
|
||||
} catch (InsertBlankWordException e) {
|
||||
Logger.e("tt9/showAddWord", e.getMessage());
|
||||
UI.toastLong(this, R.string.add_word_blank);
|
||||
return;
|
||||
} catch (InvalidLanguageException e) {
|
||||
Logger.e("tt9/showAddWord", e.getMessage());
|
||||
UI.toastLong(this, R.string.add_word_invalid_language);
|
||||
return;
|
||||
} catch (NotActiveException e) {
|
||||
UI.toastLong(this, e.getMessage());
|
||||
return;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
acceptCurrentSuggestion();
|
||||
clearSuggestions();
|
||||
|
||||
String template = "";
|
||||
|
||||
// @todo: get the current word template from the input connection
|
||||
// template = getSurroundingWord();
|
||||
|
||||
UI.showAddWordDialog(this, mLanguage.getId(), template);
|
||||
UI.showAddWordDialog(this, mLanguage.getId(), InputFieldHelper.getSurroundingWord(currentInputConnection));
|
||||
}
|
||||
|
||||
|
||||
private void restoreLastWordIfAny() {
|
||||
// mAddingWord = false;
|
||||
/**
|
||||
* restoreAddedWordIfAny
|
||||
* If a new word was added to the dictionary, this function will append add it to the current input field.
|
||||
*/
|
||||
private void restoreAddedWordIfAny() {
|
||||
String word = prefs.getLastWord();
|
||||
if (word.equals("")) {
|
||||
prefs.saveLastWord("");
|
||||
prefs.clearLastWord();
|
||||
|
||||
// @todo: push the word to the text field
|
||||
if (word.length() == 0 || word.equals(InputFieldHelper.getSurroundingWord(currentInputConnection))) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Logger.d("restoreAddedWordIfAny", "Restoring word: '" + word + "'...");
|
||||
predictionSequence = mLanguage.getDigitSequenceForWord(word);
|
||||
currentInputConnection.commitText(word, word.length());
|
||||
} catch (Exception e) {
|
||||
Logger.w("tt9/restoreLastWord", "Could not restore the last added word. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* createSoftKeyView
|
||||
* Generates the actual UI of TT9.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package io.github.sspanak.tt9.languages;
|
||||
|
||||
public class InvalidLanguageException extends Exception {
|
||||
public InvalidLanguageException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
public InvalidLanguageException() { super("Invalid Language"); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ public class T9Preferences {
|
|||
|
||||
public void saveEnabledLanguages(ArrayList<Integer> languageIds) {
|
||||
int languageMask = 0;
|
||||
for (Integer langId : languageIds) {
|
||||
for (int langId : languageIds) {
|
||||
if (!validateSavedLanguage(langId, "tt9/saveEnabledLanguages")){
|
||||
continue;
|
||||
}
|
||||
|
|
@ -172,4 +172,9 @@ public class T9Preferences {
|
|||
prefsEditor.putString("last_word", lastWord);
|
||||
prefsEditor.apply();
|
||||
}
|
||||
|
||||
public void clearLastWord() {
|
||||
this.saveLastWord("");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,17 @@ package io.github.sspanak.tt9.ui;
|
|||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.db.DictionaryDb;
|
||||
import io.github.sspanak.tt9.db.InsertBlankWordException;
|
||||
import io.github.sspanak.tt9.languages.InvalidLanguageException;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.preferences.T9Preferences;
|
||||
|
||||
|
|
@ -17,55 +21,71 @@ public class AddWordAct extends Activity {
|
|||
|
||||
View main;
|
||||
int lang;
|
||||
String origword;
|
||||
String word;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedData) {
|
||||
super.onCreate(savedData);
|
||||
View v = getLayoutInflater().inflate(R.layout.addwordview, null);
|
||||
EditText et = (EditText) v.findViewById(R.id.add_word_text);
|
||||
Intent i = getIntent();
|
||||
origword = i.getStringExtra("io.github.sspanak.tt9.word");
|
||||
|
||||
word = i.getStringExtra("io.github.sspanak.tt9.word");
|
||||
lang = i.getIntExtra("io.github.sspanak.tt9.lang", -1);
|
||||
if (lang == -1) {
|
||||
Logger.e("AddWordAct.onCreate", "lang is invalid. How?");
|
||||
}
|
||||
// Logger.d("AddWord", "data.get: " + word);
|
||||
et.setText(origword);
|
||||
et.setSelection(origword.length());
|
||||
|
||||
View v = getLayoutInflater().inflate(R.layout.addwordview, null);
|
||||
|
||||
EditText et = (EditText) v.findViewById(R.id.add_word_text);
|
||||
et.setText(word);
|
||||
et.setSelection(word.length());
|
||||
setContentView(v);
|
||||
main = v;
|
||||
}
|
||||
|
||||
public void addWordButton(View v) {
|
||||
EditText et = (EditText) main.findViewById(R.id.add_word_text);
|
||||
// Logger.d("AddWordAct", "adding word: " + et.getText());
|
||||
doAddWord(et.getText().toString());
|
||||
this.finish();
|
||||
}
|
||||
|
||||
public void doAddWord(String text) {
|
||||
try {
|
||||
DictionaryDb.insertWord(this, text, LanguageCollection.getLanguage(lang).getId());
|
||||
} catch (Exception e) {
|
||||
UI.toast(this, e.getMessage());
|
||||
return;
|
||||
private final Handler onAddedWord = new Handler(Looper.getMainLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case 0:
|
||||
Logger.d("onAddedWord", "Added word: '" + word + "'...");
|
||||
T9Preferences.getInstance(main.getContext()).saveLastWord(word);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
UI.toastLong(
|
||||
main.getContext(),
|
||||
getResources().getString(R.string.add_word_exist, word)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
UI.toastLong(main.getContext(), R.string.error_unexpected);
|
||||
break;
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
};
|
||||
|
||||
public void addWord(View v) {
|
||||
try {
|
||||
// re-fetch the word, in case the user has changed it after the initialization
|
||||
word = ((EditText) main.findViewById(R.id.add_word_text)).getText().toString();
|
||||
Logger.d("addWord", "Attempting to add word: '" + word + "'...");
|
||||
|
||||
DictionaryDb.insertWord(this, onAddedWord, LanguageCollection.getLanguage(lang), word);
|
||||
} catch (InsertBlankWordException e) {
|
||||
Logger.e("AddWordAct.addWord", e.getMessage());
|
||||
UI.toastLong(this, R.string.add_word_blank);
|
||||
} catch (InvalidLanguageException e) {
|
||||
Logger.e("AddWordAct.addWord", "Cannot insert a word for language with ID: '" + lang + "'. " + e.getMessage());
|
||||
UI.toastLong(this, R.string.add_word_invalid_language);
|
||||
} catch (Exception e) {
|
||||
Logger.e("AddWordAct.addWord", e.getMessage());
|
||||
UI.toastLong(this, e.getMessage());
|
||||
}
|
||||
T9Preferences.getInstance(this).saveLastWord(text);
|
||||
}
|
||||
|
||||
|
||||
public void cancelButton(View v) {
|
||||
// Logger.d("AddWordAct", "Cancelled...");
|
||||
public void cancelAddingWord(View v) {
|
||||
this.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.add_word, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -418,11 +418,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
// get settings
|
||||
T9Preferences prefs = new T9Preferences(this);
|
||||
Object[] settings = {
|
||||
prefs.getInputMode(),
|
||||
0, // input languages; not used, remove in #29
|
||||
null, // MODE_NOTIFY; not used, remove in #29
|
||||
false, // KEY_REMAP; not used, remove in #29
|
||||
true, // SPACE_ZERO; not used, remove in #29
|
||||
prefs.getInputMode()
|
||||
};
|
||||
ListAdapter settingitems;
|
||||
try {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue