diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fed9250e..1e8e5cff 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,13 +50,17 @@ To support a new language one needs to: - Create a proper icon for each screen size. The icon needs to contain the abbreviation of the language. (e.g. "En" for "English"). - The font must be Roboto Lt at an adequate size to fit the icon square with minimum padding. - The text must be white and the background must be transparent as per the [official Android guide](https://android-doc.github.io/guide/practices/ui_guidelines/icon_design_status_bar.html). - - To simplify the process, you could use Android Studio. It has a built-in icon generator accessible by right-cicking on "drawable" folder -> New -> Image Asset. Then choose "Icon Type": "Notification Icons", "Asset Type": Text, "Trim": No, "Padding": 0%. -- Find a suitable dictionary and add it to `assets` folder. Two file formats are supported, [see below](#dictionary-formats). + - To simplify the process, you could use Android Studio. It has a built-in icon generator accessible by right-clicking on "drawable" folder -> New -> Image Asset. Then choose "Icon Type": "Notification Icons", "Asset Type": Text, "Trim": No, "Padding": 0%. +- Find a suitable dictionary and add it to `assets/` folder. Two file formats are supported, [see below](#dictionary-formats). - Do not forget to include the dictionary license (or readme) file in the `docs/` folder. -- Create a new language class in `languages/definitions/`. Make sure to set all properties. - - `ID` must be the next available number. - - Set `isPunctuationPartOfWords` to `true`, if you need to use the 1-key for typing words, such as: `it's`, `a'tje` or `п'ят`. Otherwise, it would not be possible to type them, nor will they appear as suggestions. `false` will allow faster typing when apostrophes or other punctuation are not part of the words. -- Add the new language to the list in `LanguageCollection.java`. You only need to add it in one place, in the constructor. Please, be nice and maintain the alphabetical order. +- Create a new language class in `languages/definitions/` and define its properties. + - `name` is the native name of the language (e.g. "English", "Deutsch", "Українська"). + - `locale` contains the language and the country codes (e.g. "en-US", "es-AR", "it-IT"). Refer to the list of [supported locales in Java](https://www.oracle.com/java/technologies/javase/jdk8-jre8-suported-locales.html#util-text). + - `dictionaryFile` is the name of the dictionary in `assets/` folder. + - `icon`, `abcLowerCaseIcon` and `abcUpperCaseIcon` are the respective status icons for Predictive mode, ABC (lowercase) and ABC (uppercase). + - Set `isPunctuationPartOfWords` to `true`, if the dictionary contains words with apostrophes or dashes, such as: `it's`, `you'll`, `a'tje` or `п'ят`. This will allow using 1-key for typing them (they will appear as suggestions). `false` will enable faster typing when apostrophes or other punctuation are not part of the words (no such words will be suggested). + - `characterMap` contains the letters and punctuation marks associated with each key. +- Finally, add the new language to the list in `LanguageCollection.java`. You only need to add it in one place, in the constructor. Please, be nice and maintain the alphabetical order. ### Dictionary Formats @@ -67,7 +71,7 @@ The most basic format is just a list of words where each word is on a new line. Constraints: - No single lowercase letters. The application will add them automatically. - No repeating words. -- No digits or garbadge characters as part of the words. +- No digits or garbage characters as part of the words. _The constraints will be verified automatically upon building._ @@ -108,8 +112,7 @@ Alternatively, if you don't have Android Studio, you could just use `res/values/ ## Adding Support for Keys TT9 allows assigning hotkeys for performing different functions. If your phone has a special key that does not appear on the Hotkey configuration screen, you can easily add support for it. -- Find [preferences/helpers/Hotkeys.java](io/github/sspanak/tt9/preferences/helpers/Hotkeys.java). -- In the file, find the `generateList()` function. +- In `preferences/helpers/Hotkeys.java`, find the `generateList()` function. - Add the new key there. The order of adding is used when displaying the dropdown options. - Optionally, you can translate the name of the key in different languages in the `res/values-XX/strings.xml` files. diff --git a/src/io/github/sspanak/tt9/db/DictionaryDb.java b/src/io/github/sspanak/tt9/db/DictionaryDb.java index a344dd50..b23388c2 100644 --- a/src/io/github/sspanak/tt9/db/DictionaryDb.java +++ b/src/io/github/sspanak/tt9/db/DictionaryDb.java @@ -6,38 +6,26 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; -import androidx.annotation.NonNull; -import androidx.room.Room; -import androidx.room.RoomDatabase; -import androidx.sqlite.db.SupportSQLiteDatabase; - import java.util.ArrayList; import java.util.List; import io.github.sspanak.tt9.Logger; +import io.github.sspanak.tt9.db.exceptions.InsertBlankWordException; +import io.github.sspanak.tt9.db.room.TT9Room; +import io.github.sspanak.tt9.db.room.Word; import io.github.sspanak.tt9.ime.TraditionalT9; import io.github.sspanak.tt9.languages.InvalidLanguageException; import io.github.sspanak.tt9.languages.Language; import io.github.sspanak.tt9.preferences.SettingsStore; public class DictionaryDb { - private static T9RoomDb dbInstance; - - private static final RoomDatabase.Callback DROP_NORMALIZATION_TRIGGER = new RoomDatabase.Callback() { - @Override - public void onOpen(@NonNull SupportSQLiteDatabase db) { - super.onOpen(db); - db.execSQL("DROP TRIGGER IF EXISTS normalize_freq"); - } - }; + private static TT9Room dbInstance; public static synchronized void init(Context context) { if (dbInstance == null) { context = context == null ? TraditionalT9.getMainContext() : context; - dbInstance = Room.databaseBuilder(context, T9RoomDb.class, "t9dict.db") - .addCallback(DROP_NORMALIZATION_TRIGGER) // @todo: Remove trigger dropping after December 2023. Assuming everyone would have upgraded by then. - .build(); + dbInstance = TT9Room.getInstance(context); } } @@ -47,7 +35,7 @@ public class DictionaryDb { } - private static T9RoomDb getInstance() { + private static TT9Room getInstance() { init(); return dbInstance; } diff --git a/src/io/github/sspanak/tt9/db/DictionaryLoader.java b/src/io/github/sspanak/tt9/db/DictionaryLoader.java index a9824030..a05db5b2 100644 --- a/src/io/github/sspanak/tt9/db/DictionaryLoader.java +++ b/src/io/github/sspanak/tt9/db/DictionaryLoader.java @@ -11,9 +11,12 @@ import java.io.InputStreamReader; import java.io.LineNumberReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.regex.Pattern; import io.github.sspanak.tt9.Logger; +import io.github.sspanak.tt9.db.exceptions.DictionaryImportAbortedException; +import io.github.sspanak.tt9.db.exceptions.DictionaryImportAlreadyRunningException; +import io.github.sspanak.tt9.db.exceptions.DictionaryImportException; +import io.github.sspanak.tt9.db.room.Word; import io.github.sspanak.tt9.languages.InvalidLanguageCharactersException; import io.github.sspanak.tt9.languages.InvalidLanguageException; import io.github.sspanak.tt9.languages.Language; diff --git a/src/io/github/sspanak/tt9/db/T9RoomDb.java b/src/io/github/sspanak/tt9/db/T9RoomDb.java deleted file mode 100644 index 0af5a83d..00000000 --- a/src/io/github/sspanak/tt9/db/T9RoomDb.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.sspanak.tt9.db; - -import androidx.room.Database; -import androidx.room.RoomDatabase; - -@Database(version = 5, entities = Word.class, exportSchema = false) -abstract class T9RoomDb extends RoomDatabase { - public abstract WordsDao wordsDao(); -} diff --git a/src/io/github/sspanak/tt9/db/DictionaryImportAbortedException.java b/src/io/github/sspanak/tt9/db/exceptions/DictionaryImportAbortedException.java similarity index 78% rename from src/io/github/sspanak/tt9/db/DictionaryImportAbortedException.java rename to src/io/github/sspanak/tt9/db/exceptions/DictionaryImportAbortedException.java index 25c6f4b5..c721752f 100644 --- a/src/io/github/sspanak/tt9/db/DictionaryImportAbortedException.java +++ b/src/io/github/sspanak/tt9/db/exceptions/DictionaryImportAbortedException.java @@ -1,4 +1,4 @@ -package io.github.sspanak.tt9.db; +package io.github.sspanak.tt9.db.exceptions; public class DictionaryImportAbortedException extends Exception{ public DictionaryImportAbortedException() { diff --git a/src/io/github/sspanak/tt9/db/DictionaryImportAlreadyRunningException.java b/src/io/github/sspanak/tt9/db/exceptions/DictionaryImportAlreadyRunningException.java similarity index 80% rename from src/io/github/sspanak/tt9/db/DictionaryImportAlreadyRunningException.java rename to src/io/github/sspanak/tt9/db/exceptions/DictionaryImportAlreadyRunningException.java index a50b5b33..b1c2c4e9 100644 --- a/src/io/github/sspanak/tt9/db/DictionaryImportAlreadyRunningException.java +++ b/src/io/github/sspanak/tt9/db/exceptions/DictionaryImportAlreadyRunningException.java @@ -1,4 +1,4 @@ -package io.github.sspanak.tt9.db; +package io.github.sspanak.tt9.db.exceptions; public class DictionaryImportAlreadyRunningException extends Exception{ public DictionaryImportAlreadyRunningException() { diff --git a/src/io/github/sspanak/tt9/db/DictionaryImportException.java b/src/io/github/sspanak/tt9/db/exceptions/DictionaryImportException.java similarity index 67% rename from src/io/github/sspanak/tt9/db/DictionaryImportException.java rename to src/io/github/sspanak/tt9/db/exceptions/DictionaryImportException.java index 6a3fd087..2d91502a 100644 --- a/src/io/github/sspanak/tt9/db/DictionaryImportException.java +++ b/src/io/github/sspanak/tt9/db/exceptions/DictionaryImportException.java @@ -1,11 +1,11 @@ -package io.github.sspanak.tt9.db; +package io.github.sspanak.tt9.db.exceptions; public class DictionaryImportException extends Exception { public final String file; public final String word; public final long line; - DictionaryImportException(String file, String word, long line) { + public DictionaryImportException(String file, String word, long line) { super("Dictionary import failed"); this.file = file; this.word = word; diff --git a/src/io/github/sspanak/tt9/db/InsertBlankWordException.java b/src/io/github/sspanak/tt9/db/exceptions/InsertBlankWordException.java similarity index 55% rename from src/io/github/sspanak/tt9/db/InsertBlankWordException.java rename to src/io/github/sspanak/tt9/db/exceptions/InsertBlankWordException.java index b6869b75..48eecd84 100644 --- a/src/io/github/sspanak/tt9/db/InsertBlankWordException.java +++ b/src/io/github/sspanak/tt9/db/exceptions/InsertBlankWordException.java @@ -1,7 +1,7 @@ -package io.github.sspanak.tt9.db; +package io.github.sspanak.tt9.db.exceptions; public class InsertBlankWordException extends Exception { - protected InsertBlankWordException() { + public InsertBlankWordException() { super("Cannot insert a blank word."); } } diff --git a/src/io/github/sspanak/tt9/db/migrations/DB6.java b/src/io/github/sspanak/tt9/db/migrations/DB6.java new file mode 100644 index 00000000..bbeadf96 --- /dev/null +++ b/src/io/github/sspanak/tt9/db/migrations/DB6.java @@ -0,0 +1,13 @@ +package io.github.sspanak.tt9.db.migrations; + +import androidx.room.migration.Migration; +import androidx.sqlite.db.SupportSQLiteDatabase; + +public class DB6 { + public static final Migration MIGRATION = new Migration(5, 6) { + @Override + public void migrate(SupportSQLiteDatabase database) { + database.execSQL("DROP TRIGGER IF EXISTS normalize_freq"); + } + }; +} diff --git a/src/io/github/sspanak/tt9/db/migrations/DB7.java b/src/io/github/sspanak/tt9/db/migrations/DB7.java new file mode 100644 index 00000000..4e8b662c --- /dev/null +++ b/src/io/github/sspanak/tt9/db/migrations/DB7.java @@ -0,0 +1,82 @@ +package io.github.sspanak.tt9.db.migrations; + +import android.content.Context; + +import androidx.room.migration.Migration; +import androidx.sqlite.db.SupportSQLiteDatabase; + +import java.util.ArrayList; + +import io.github.sspanak.tt9.languages.definitions.Bulgarian; +import io.github.sspanak.tt9.languages.definitions.Dutch; +import io.github.sspanak.tt9.languages.definitions.English; +import io.github.sspanak.tt9.languages.definitions.French; +import io.github.sspanak.tt9.languages.definitions.German; +import io.github.sspanak.tt9.languages.definitions.Italian; +import io.github.sspanak.tt9.languages.definitions.Russian; +import io.github.sspanak.tt9.languages.definitions.Spanish; +import io.github.sspanak.tt9.languages.definitions.Ukrainian; +import io.github.sspanak.tt9.preferences.SettingsStore; + +public class DB7 { + private Context ctx; + + public Migration getMigration(Context context) { + ctx = context; + return migration; + } + + private int getNewLanguageId(int oldId) { + switch (oldId) { + default: + return oldId; + case 1: + return new English().getId(); + case 2: + return new Russian().getId(); + case 3: + return new German().getId(); + case 4: + return new French().getId(); + case 5: + return new Italian().getId(); + case 6: + return new Ukrainian().getId(); + case 7: + return new Bulgarian().getId(); + case 8: + return new Dutch().getId(); + case 9: + return new Spanish().getId(); + } + } + + private final Migration migration = new Migration(6, 7) { + private void migrateSQL(SupportSQLiteDatabase database) { + for (int oldLangId = 1; oldLangId <= 9; oldLangId++) { + database.execSQL( + "UPDATE words " + + " SET lang = " + getNewLanguageId(oldLangId) + + " WHERE lang = " + oldLangId + ); + } + } + + private void migrateSettings() { + SettingsStore settings = new SettingsStore(ctx); + + ArrayList newLangIds = new ArrayList<>(); + for (int langId : settings.getEnabledLanguageIds()) { + newLangIds.add(getNewLanguageId(langId)); + } + + settings.saveEnabledLanguageIds(newLangIds); + } + + @Override + public void migrate(SupportSQLiteDatabase database) { + migrateSQL(database); + migrateSettings(); + } + }; +} diff --git a/src/io/github/sspanak/tt9/db/room/TT9Room.java b/src/io/github/sspanak/tt9/db/room/TT9Room.java new file mode 100644 index 00000000..49429f05 --- /dev/null +++ b/src/io/github/sspanak/tt9/db/room/TT9Room.java @@ -0,0 +1,22 @@ +package io.github.sspanak.tt9.db.room; + +import android.content.Context; + +import androidx.room.Database; +import androidx.room.Room; +import androidx.room.RoomDatabase; + +import io.github.sspanak.tt9.db.migrations.DB6; +import io.github.sspanak.tt9.db.migrations.DB7; + +@Database(version = 7, entities = Word.class, exportSchema = false) +public abstract class TT9Room extends RoomDatabase { + public abstract WordsDao wordsDao(); + + public static synchronized TT9Room getInstance(Context context) { + return Room + .databaseBuilder(context, TT9Room.class, "t9dict.db") + .addMigrations(DB6.MIGRATION, new DB7().getMigration(context)) + .build(); + } +} diff --git a/src/io/github/sspanak/tt9/db/Word.java b/src/io/github/sspanak/tt9/db/room/Word.java similarity index 92% rename from src/io/github/sspanak/tt9/db/Word.java rename to src/io/github/sspanak/tt9/db/room/Word.java index 1503b81b..8ca8d0c3 100644 --- a/src/io/github/sspanak/tt9/db/Word.java +++ b/src/io/github/sspanak/tt9/db/room/Word.java @@ -1,4 +1,4 @@ -package io.github.sspanak.tt9.db; +package io.github.sspanak.tt9.db.room; import androidx.room.ColumnInfo; import androidx.room.Entity; diff --git a/src/io/github/sspanak/tt9/db/WordsDao.java b/src/io/github/sspanak/tt9/db/room/WordsDao.java similarity index 93% rename from src/io/github/sspanak/tt9/db/WordsDao.java rename to src/io/github/sspanak/tt9/db/room/WordsDao.java index 59364ed5..bcffb548 100644 --- a/src/io/github/sspanak/tt9/db/WordsDao.java +++ b/src/io/github/sspanak/tt9/db/room/WordsDao.java @@ -1,4 +1,4 @@ -package io.github.sspanak.tt9.db; +package io.github.sspanak.tt9.db.room; import androidx.room.Dao; import androidx.room.Insert; @@ -9,12 +9,12 @@ import java.util.ArrayList; import java.util.List; @Dao -interface WordsDao { +public interface WordsDao { @Query("SELECT COUNT(id) FROM words WHERE :langId < 0 OR lang = :langId") int count(int langId); @Query("DELETE FROM words WHERE LANG IN(:langIds)") - int deleteByLanguage(ArrayList langIds); + void deleteByLanguage(ArrayList langIds); @Query("SELECT COUNT(id) FROM words WHERE lang = :langId AND word = :word") int doesWordExist(int langId, String word); diff --git a/src/io/github/sspanak/tt9/ime/TraditionalT9.java b/src/io/github/sspanak/tt9/ime/TraditionalT9.java index c903fe8c..a6bf392c 100644 --- a/src/io/github/sspanak/tt9/ime/TraditionalT9.java +++ b/src/io/github/sspanak/tt9/ime/TraditionalT9.java @@ -63,7 +63,7 @@ public class TraditionalT9 extends KeyPadHandler { private void validateFunctionKeys() { - if (!settings.areFunctionKeysSet()) { + if (settings.isSettingsKeyMissing()) { settings.setDefaultKeys(); } } @@ -531,10 +531,15 @@ public class TraditionalT9 extends KeyPadHandler { return false; } + // when only one language is enabled, just acknowledge the key was pressed + if (mEnabledLanguages.size() < 2) { + return true; + } + // select the next language - int previousLangId = mEnabledLanguages.indexOf(mLanguage.getId()); - int nextLangId = previousLangId == -1 ? 0 : (previousLangId + 1) % mEnabledLanguages.size(); - mLanguage = LanguageCollection.getLanguage(mEnabledLanguages.get(nextLangId)); + int previous = mEnabledLanguages.indexOf(mLanguage.getId()); + int next = (previous + 1) % mEnabledLanguages.size(); + mLanguage = LanguageCollection.getLanguage(mEnabledLanguages.get(next)); validateLanguages(); diff --git a/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java b/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java index ddcc752c..029c2b56 100644 --- a/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java +++ b/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java @@ -6,7 +6,6 @@ import io.github.sspanak.tt9.Logger; import io.github.sspanak.tt9.ime.modes.InputMode; import io.github.sspanak.tt9.languages.Language; import io.github.sspanak.tt9.languages.LanguageCollection; -import io.github.sspanak.tt9.languages.definitions.English; import io.github.sspanak.tt9.preferences.SettingsStore; public class InputModeValidator { @@ -17,7 +16,7 @@ public class InputModeValidator { validLanguageIds.add(lang.getId()); } if (validLanguageIds.size() == 0) { - validLanguageIds.add(1); + validLanguageIds.add(LanguageCollection.getDefault().getId()); Logger.e("tt9/validateEnabledLanguages", "The language list seems to be corrupted. Resetting to first language only."); } @@ -34,8 +33,7 @@ public class InputModeValidator { String error = language != null ? "Language: " + language.getId() + " is not enabled." : "Invalid language."; Language validLanguage = LanguageCollection.getLanguage(validLanguageIds.get(0)); - validLanguage = validLanguage == null ? LanguageCollection.getLanguage(1) : validLanguage; - validLanguage = validLanguage == null ? new English() : validLanguage; + validLanguage = validLanguage != null ? validLanguage : LanguageCollection.getDefault(); settings.saveInputLanguage(validLanguage.getId()); Logger.w("tt9/validateSavedLanguage", error + " Enforcing language: " + validLanguage.getId()); diff --git a/src/io/github/sspanak/tt9/languages/Language.java b/src/io/github/sspanak/tt9/languages/Language.java index 21c68149..80158d8b 100644 --- a/src/io/github/sspanak/tt9/languages/Language.java +++ b/src/io/github/sspanak/tt9/languages/Language.java @@ -8,7 +8,7 @@ import java.util.Locale; public class Language { - protected int id; + private int id; protected String name; protected Locale locale; protected int icon; @@ -22,6 +22,10 @@ public class Language { protected boolean isPunctuationPartOfWords; // see the getter for more info final public int getId() { + if (id == 0) { + id = generateId(); + } + return id; } @@ -45,7 +49,6 @@ public class Language { return lowerCase ? abcLowerCaseIcon : abcUpperCaseIcon; } - /** * isPunctuationPartOfWords * This plays a role in Predictive mode only. @@ -65,7 +68,35 @@ public class Language { final public boolean isPunctuationPartOfWords() { return isPunctuationPartOfWords; } - /************* utility *************/ + /* ************ utility ************ */ + + /** + * generateId + * Uses the letters of the Locale to generate an ID for the language. + * Each letter is converted to uppercase and used as n 5-bit integer. Then the the 5-bits + * are packed to form a 10-bit or a 20-bit integer, depending on the Locale. + * + * Example (2-letter Locale) + * "en" + * -> "E" | "N" + * -> 5 | 448 (shift the 2nd number by 5 bits, so its bits would not overlap with the 1st one) + * -> 543 + * + * Example (4-letter Locale) + * "bg-BG" + * -> "B" | "G" | "B" | "G" + * -> 2 | 224 | 2048 | 229376 (shift each 5-bit number, not overlap with the previous ones) + * -> 231650 + */ + private int generateId() { + String idString = (locale.getLanguage() + locale.getCountry()).toUpperCase(); + int idInt = 0; + for (int i = 0; i < idString.length(); i++) { + idInt |= ((idString.charAt(i) & 31) << (i * 5)); + } + + return idInt; + } private void generateReverseCharacterMap() { reverseCharacterMap.clear(); @@ -76,7 +107,6 @@ public class Language { } } - public String capitalize(String word) { return word != null ? word.substring(0, 1).toUpperCase(locale) + word.substring(1).toLowerCase(locale) : null; } diff --git a/src/io/github/sspanak/tt9/languages/LanguageCollection.java b/src/io/github/sspanak/tt9/languages/LanguageCollection.java index e201875a..af8d5270 100644 --- a/src/io/github/sspanak/tt9/languages/LanguageCollection.java +++ b/src/io/github/sspanak/tt9/languages/LanguageCollection.java @@ -14,6 +14,7 @@ import io.github.sspanak.tt9.languages.definitions.*; public class LanguageCollection { private static LanguageCollection self; + private final Language defaultLanguage = new English(); private final HashMap languages = new HashMap<>(); private LanguageCollection() { @@ -61,6 +62,10 @@ public class LanguageCollection { return null; } + public static Language getDefault() { + return getInstance().defaultLanguage; + } + public static ArrayList getAll(ArrayList languageIds, boolean sort) { ArrayList langList = new ArrayList<>(); diff --git a/src/io/github/sspanak/tt9/languages/definitions/Bulgarian.java b/src/io/github/sspanak/tt9/languages/definitions/Bulgarian.java index 00c457b1..aef48f24 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/Bulgarian.java +++ b/src/io/github/sspanak/tt9/languages/definitions/Bulgarian.java @@ -10,7 +10,6 @@ import io.github.sspanak.tt9.languages.Characters; public class Bulgarian extends Language { public Bulgarian() { - id = 7; name = "Български"; locale = new Locale("bg","BG"); dictionaryFile = "bg-utf8.csv"; diff --git a/src/io/github/sspanak/tt9/languages/definitions/Dutch.java b/src/io/github/sspanak/tt9/languages/definitions/Dutch.java index f15c9723..7e434007 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/Dutch.java +++ b/src/io/github/sspanak/tt9/languages/definitions/Dutch.java @@ -9,7 +9,6 @@ public class Dutch extends English { public Dutch() { super(); - id = 8; name = "Nederlands"; locale = new Locale("nl","NL"); dictionaryFile = "nl-utf8.csv"; diff --git a/src/io/github/sspanak/tt9/languages/definitions/English.java b/src/io/github/sspanak/tt9/languages/definitions/English.java index 7e166e87..9d4671e9 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/English.java +++ b/src/io/github/sspanak/tt9/languages/definitions/English.java @@ -10,7 +10,6 @@ import io.github.sspanak.tt9.languages.Characters; public class English extends Language { public English() { - id = 1; name = "English"; locale = Locale.ENGLISH; dictionaryFile = "en-utf8.csv"; diff --git a/src/io/github/sspanak/tt9/languages/definitions/French.java b/src/io/github/sspanak/tt9/languages/definitions/French.java index 6f755af9..2113d19e 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/French.java +++ b/src/io/github/sspanak/tt9/languages/definitions/French.java @@ -9,7 +9,6 @@ public class French extends English { public French() { super(); - id = 4; name = "Français"; locale = Locale.FRENCH; dictionaryFile = "fr-utf8.csv"; diff --git a/src/io/github/sspanak/tt9/languages/definitions/German.java b/src/io/github/sspanak/tt9/languages/definitions/German.java index 7bee1fb5..6d477308 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/German.java +++ b/src/io/github/sspanak/tt9/languages/definitions/German.java @@ -8,7 +8,6 @@ public class German extends English { public German() { super(); - id = 3; name = "Deutsch"; locale = Locale.GERMAN; dictionaryFile = "de-utf8.csv"; diff --git a/src/io/github/sspanak/tt9/languages/definitions/Italian.java b/src/io/github/sspanak/tt9/languages/definitions/Italian.java index 30a4bc71..cac48d91 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/Italian.java +++ b/src/io/github/sspanak/tt9/languages/definitions/Italian.java @@ -9,7 +9,6 @@ public class Italian extends English { public Italian() { super(); - id = 5; name = "Italiano"; locale = Locale.ITALIAN; dictionaryFile = "it-utf8.csv"; diff --git a/src/io/github/sspanak/tt9/languages/definitions/Russian.java b/src/io/github/sspanak/tt9/languages/definitions/Russian.java index 4c512a43..0a848f95 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/Russian.java +++ b/src/io/github/sspanak/tt9/languages/definitions/Russian.java @@ -10,7 +10,6 @@ import io.github.sspanak.tt9.languages.Characters; public class Russian extends Language { public Russian() { - id = 2; name = "Русский"; locale = new Locale("ru","RU"); dictionaryFile = "ru-utf8.csv"; diff --git a/src/io/github/sspanak/tt9/languages/definitions/Spanish.java b/src/io/github/sspanak/tt9/languages/definitions/Spanish.java index 0e8e8d72..b44631ba 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/Spanish.java +++ b/src/io/github/sspanak/tt9/languages/definitions/Spanish.java @@ -12,7 +12,6 @@ public class Spanish extends English { public Spanish() { super(); - id = 9; name = "Español"; locale = new Locale("es", "ES"); dictionaryFile = "es-utf8.csv"; diff --git a/src/io/github/sspanak/tt9/languages/definitions/Ukrainian.java b/src/io/github/sspanak/tt9/languages/definitions/Ukrainian.java index 63fd6115..d24aca95 100644 --- a/src/io/github/sspanak/tt9/languages/definitions/Ukrainian.java +++ b/src/io/github/sspanak/tt9/languages/definitions/Ukrainian.java @@ -10,7 +10,6 @@ import io.github.sspanak.tt9.languages.Characters; public class Ukrainian extends Language { public Ukrainian() { - id = 6; name = "Українська"; locale = new Locale("uk","UA"); dictionaryFile = "uk-utf8.csv"; diff --git a/src/io/github/sspanak/tt9/preferences/PreferencesActivity.java b/src/io/github/sspanak/tt9/preferences/PreferencesActivity.java index a2be40c7..62140cec 100644 --- a/src/io/github/sspanak/tt9/preferences/PreferencesActivity.java +++ b/src/io/github/sspanak/tt9/preferences/PreferencesActivity.java @@ -14,6 +14,7 @@ import androidx.preference.PreferenceFragmentCompat; import io.github.sspanak.tt9.R; import io.github.sspanak.tt9.db.DictionaryDb; import io.github.sspanak.tt9.db.DictionaryLoader; +import io.github.sspanak.tt9.ime.helpers.InputModeValidator; import io.github.sspanak.tt9.preferences.screens.AppearanceScreen; import io.github.sspanak.tt9.preferences.screens.DictionariesScreen; import io.github.sspanak.tt9.preferences.screens.HotkeysScreen; @@ -33,6 +34,8 @@ public class PreferencesActivity extends AppCompatActivity implements Preference DictionaryDb.init(this); DictionaryDb.normalizeWordFrequencies(settings); + InputModeValidator.validateEnabledLanguages(settings, settings.getEnabledLanguageIds()); + super.onCreate(savedInstanceState); validateFunctionKeys(); buildLayout(); @@ -125,7 +128,7 @@ public class PreferencesActivity extends AppCompatActivity implements Preference private void validateFunctionKeys() { - if (!settings.areFunctionKeysSet()) { + if (settings.isSettingsKeyMissing()) { settings.setDefaultKeys(); } } diff --git a/src/io/github/sspanak/tt9/preferences/SettingsStore.java b/src/io/github/sspanak/tt9/preferences/SettingsStore.java index 6d727653..4a171140 100644 --- a/src/io/github/sspanak/tt9/preferences/SettingsStore.java +++ b/src/io/github/sspanak/tt9/preferences/SettingsStore.java @@ -70,7 +70,9 @@ public class SettingsStore { } public Set getEnabledLanguagesIdsAsStrings() { - return prefs.getStringSet("pref_languages", new HashSet<>(Collections.singletonList("1"))); + return prefs.getStringSet("pref_languages", new HashSet<>(Collections.singletonList( + String.valueOf(LanguageCollection.getDefault().getId()) + ))); } public void saveEnabledLanguageIds(ArrayList languageIds) { @@ -123,7 +125,7 @@ public class SettingsStore { public int getInputLanguage() { - return prefs.getInt("pref_input_language", 1); + return prefs.getInt("pref_input_language", LanguageCollection.getDefault().getId()); } public void saveInputLanguage(int language) { @@ -151,8 +153,8 @@ public class SettingsStore { /************* function key settings *************/ - public boolean areFunctionKeysSet() { - return getKeyShowSettings() != 0; + public boolean isSettingsKeyMissing() { + return getKeyShowSettings() == 0; } public void setDefaultKeys() { @@ -198,7 +200,6 @@ public class SettingsStore { public boolean getNotifyNextLanguageInModeAbc() { return prefs.getBoolean("notify_next_language_in_mode_abc", true); } public boolean getDarkTheme() { return prefs.getBoolean("pref_dark_theme", true); } - public void setDarkTheme(boolean yes) { prefsEditor.putBoolean("pref_dark_theme", yes); } public boolean getShowSoftKeys() { return prefs.getBoolean("pref_show_soft_keys", true); } diff --git a/src/io/github/sspanak/tt9/preferences/helpers/Hotkeys.java b/src/io/github/sspanak/tt9/preferences/helpers/Hotkeys.java index 31322be3..1821cbfa 100644 --- a/src/io/github/sspanak/tt9/preferences/helpers/Hotkeys.java +++ b/src/io/github/sspanak/tt9/preferences/helpers/Hotkeys.java @@ -98,7 +98,7 @@ public class Hotkeys { /** * generateList - * These keys will appears as options only if Android says the device has them. + * Generates a list of all supported hotkeys for associating functions in the Settings. * * NOTE: Some TT9 functions do not support all keys. Here you just list all possible options. * Actual validation and assigning happens in SectionKeymap.populate(). diff --git a/src/io/github/sspanak/tt9/preferences/items/ItemLoadDictionary.java b/src/io/github/sspanak/tt9/preferences/items/ItemLoadDictionary.java index 52e8b1a9..d91afefb 100644 --- a/src/io/github/sspanak/tt9/preferences/items/ItemLoadDictionary.java +++ b/src/io/github/sspanak/tt9/preferences/items/ItemLoadDictionary.java @@ -10,7 +10,7 @@ import androidx.preference.Preference; import java.util.ArrayList; import io.github.sspanak.tt9.R; -import io.github.sspanak.tt9.db.DictionaryImportAlreadyRunningException; +import io.github.sspanak.tt9.db.exceptions.DictionaryImportAlreadyRunningException; import io.github.sspanak.tt9.db.DictionaryLoader; import io.github.sspanak.tt9.languages.Language; import io.github.sspanak.tt9.languages.LanguageCollection; diff --git a/src/io/github/sspanak/tt9/ui/AddWordAct.java b/src/io/github/sspanak/tt9/ui/AddWordAct.java index 7e32925b..72611efc 100644 --- a/src/io/github/sspanak/tt9/ui/AddWordAct.java +++ b/src/io/github/sspanak/tt9/ui/AddWordAct.java @@ -14,7 +14,7 @@ import androidx.appcompat.app.AppCompatDelegate; 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.db.exceptions.InsertBlankWordException; import io.github.sspanak.tt9.languages.InvalidLanguageException; import io.github.sspanak.tt9.languages.LanguageCollection; import io.github.sspanak.tt9.preferences.SettingsStore; diff --git a/src/io/github/sspanak/tt9/ui/DictionaryLoadingBar.java b/src/io/github/sspanak/tt9/ui/DictionaryLoadingBar.java index 660a53bd..63b352a2 100644 --- a/src/io/github/sspanak/tt9/ui/DictionaryLoadingBar.java +++ b/src/io/github/sspanak/tt9/ui/DictionaryLoadingBar.java @@ -14,7 +14,7 @@ import java.io.IOException; import java.util.Locale; import io.github.sspanak.tt9.R; -import io.github.sspanak.tt9.db.DictionaryImportException; +import io.github.sspanak.tt9.db.exceptions.DictionaryImportException; import io.github.sspanak.tt9.languages.InvalidLanguageCharactersException; import io.github.sspanak.tt9.languages.InvalidLanguageException; import io.github.sspanak.tt9.languages.Language;