New settings screen stabilization
* Fixed crashes, caused by using the incorrect Android Context * Default keys are properly set the very first time Settings screen is opened * Dictionary loading status is now displayed on the Settings screen * Dictionary loading time is now displayed after operation is completed
This commit is contained in:
parent
b550d5d5dd
commit
a6fa129984
14 changed files with 171 additions and 89 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
package io.github.sspanak.tt9.db;
|
package io.github.sspanak.tt9.db;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.database.sqlite.SQLiteConstraintException;
|
import android.database.sqlite.SQLiteConstraintException;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
|
@ -43,18 +44,23 @@ public class DictionaryDb {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private static synchronized void createInstance() {
|
public static synchronized void init(Context context) {
|
||||||
dbInstance = Room.databaseBuilder(TraditionalT9.getMainContext(), T9RoomDb.class, "t9dict.db")
|
if (dbInstance == null) {
|
||||||
|
context = context == null ? TraditionalT9.getMainContext() : context;
|
||||||
|
dbInstance = Room.databaseBuilder(context, T9RoomDb.class, "t9dict.db")
|
||||||
.addCallback(TRIGGER_CALLBACK)
|
.addCallback(TRIGGER_CALLBACK)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static synchronized void init() {
|
||||||
|
init(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static T9RoomDb getInstance() {
|
private static T9RoomDb getInstance() {
|
||||||
if (dbInstance == null) {
|
init();
|
||||||
createInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbInstance;
|
return dbInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,10 @@ public class DictionaryLoader {
|
||||||
private final SettingsStore settings;
|
private final SettingsStore settings;
|
||||||
|
|
||||||
private final Pattern containsPunctuation = Pattern.compile("\\p{Punct}(?<!-)");
|
private final Pattern containsPunctuation = Pattern.compile("\\p{Punct}(?<!-)");
|
||||||
|
private Handler statusHandler = null;
|
||||||
private Thread loadThread;
|
private Thread loadThread;
|
||||||
|
|
||||||
|
private long importStartTime = 0;
|
||||||
private int currentFile = 0;
|
private int currentFile = 0;
|
||||||
private long lastProgressUpdate = 0;
|
private long lastProgressUpdate = 0;
|
||||||
|
|
||||||
|
|
@ -49,7 +51,17 @@ public class DictionaryLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void load(Handler handler, ArrayList<Language> languages) throws DictionaryImportAlreadyRunningException {
|
public void setStatusHandler(Handler handler) {
|
||||||
|
statusHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private long getImportTime() {
|
||||||
|
return System.currentTimeMillis() - importStartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void load(ArrayList<Language> languages) throws DictionaryImportAlreadyRunningException {
|
||||||
if (isRunning()) {
|
if (isRunning()) {
|
||||||
throw new DictionaryImportAlreadyRunningException();
|
throw new DictionaryImportAlreadyRunningException();
|
||||||
}
|
}
|
||||||
|
|
@ -58,12 +70,13 @@ public class DictionaryLoader {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
currentFile = 0;
|
currentFile = 0;
|
||||||
|
importStartTime = System.currentTimeMillis();
|
||||||
// SQLite does not support parallel queries, so let's import them one by one
|
// SQLite does not support parallel queries, so let's import them one by one
|
||||||
for (Language lang : languages) {
|
for (Language lang : languages) {
|
||||||
if (isInterrupted()) {
|
if (isInterrupted()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
importAll(handler, lang);
|
importAll(lang);
|
||||||
currentFile++;
|
currentFile++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -83,12 +96,12 @@ public class DictionaryLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void importAll(Handler handler, Language language) {
|
private void importAll(Language language) {
|
||||||
final String logTag = "tt9.DictionaryLoader.importAll";
|
final String logTag = "tt9.DictionaryLoader.importAll";
|
||||||
|
|
||||||
if (language == null) {
|
if (language == null) {
|
||||||
Logger.e(logTag, "Failed loading a dictionary for NULL language.");
|
Logger.e(logTag, "Failed loading a dictionary for NULL language.");
|
||||||
sendError(handler, InvalidLanguageException.class.getSimpleName(), -1);
|
sendError(InvalidLanguageException.class.getSimpleName(), -1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,7 +115,7 @@ public class DictionaryLoader {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
start = System.currentTimeMillis();
|
start = System.currentTimeMillis();
|
||||||
importWords(handler, language);
|
importWords(language);
|
||||||
Logger.i(
|
Logger.i(
|
||||||
logTag,
|
logTag,
|
||||||
"Dictionary: '" + language.getDictionaryFile() + "'" +
|
"Dictionary: '" + language.getDictionaryFile() + "'" +
|
||||||
|
|
@ -117,7 +130,7 @@ public class DictionaryLoader {
|
||||||
);
|
);
|
||||||
} catch (DictionaryImportException e) {
|
} catch (DictionaryImportException e) {
|
||||||
stop();
|
stop();
|
||||||
sendImportError(handler, DictionaryImportException.class.getSimpleName(), language.getId(), e.line, e.word);
|
sendImportError(DictionaryImportException.class.getSimpleName(), language.getId(), e.line, e.word);
|
||||||
|
|
||||||
Logger.e(
|
Logger.e(
|
||||||
logTag,
|
logTag,
|
||||||
|
|
@ -129,7 +142,7 @@ public class DictionaryLoader {
|
||||||
);
|
);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
stop();
|
stop();
|
||||||
sendError(handler, e.getClass().getSimpleName(), language.getId());
|
sendError(e.getClass().getSimpleName(), language.getId());
|
||||||
|
|
||||||
Logger.e(
|
Logger.e(
|
||||||
logTag,
|
logTag,
|
||||||
|
|
@ -168,12 +181,12 @@ public class DictionaryLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void importWords(Handler handler, Language language) throws Exception {
|
private void importWords(Language language) throws Exception {
|
||||||
importWords(handler, language, language.getDictionaryFile());
|
importWords(language, language.getDictionaryFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void importWords(Handler handler, Language language, String dictionaryFile) throws Exception {
|
private void importWords(Language language, String dictionaryFile) throws Exception {
|
||||||
long totalWords = countWords(dictionaryFile);
|
long totalWords = countWords(dictionaryFile);
|
||||||
|
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(assets.open(dictionaryFile), StandardCharsets.UTF_8));
|
BufferedReader br = new BufferedReader(new InputStreamReader(assets.open(dictionaryFile), StandardCharsets.UTF_8));
|
||||||
|
|
@ -181,17 +194,21 @@ public class DictionaryLoader {
|
||||||
ArrayList<Word> dbWords = new ArrayList<>();
|
ArrayList<Word> dbWords = new ArrayList<>();
|
||||||
long line = 0;
|
long line = 0;
|
||||||
|
|
||||||
sendProgressMessage(handler, language, 0, 0);
|
sendProgressMessage(language, 0, 0);
|
||||||
|
|
||||||
for (String word; (word = br.readLine()) != null; line++) {
|
for (String word; (word = br.readLine()) != null; line++) {
|
||||||
if (loadThread.isInterrupted()) {
|
if (loadThread.isInterrupted()) {
|
||||||
br.close();
|
br.close();
|
||||||
sendProgressMessage(handler, language, -1, 0);
|
sendProgressMessage(language, -1, 0);
|
||||||
throw new DictionaryImportAbortedException();
|
throw new DictionaryImportAbortedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
validateWord(language, word, line);
|
validateWord(language, word, line);
|
||||||
|
try {
|
||||||
dbWords.add(stringToWord(language, word));
|
dbWords.add(stringToWord(language, word));
|
||||||
|
} catch (InvalidLanguageCharactersException e) {
|
||||||
|
throw new DictionaryImportException(dictionaryFile, word, line);
|
||||||
|
}
|
||||||
|
|
||||||
if (line % settings.getDictionaryImportWordChunkSize() == 0) {
|
if (line % settings.getDictionaryImportWordChunkSize() == 0) {
|
||||||
DictionaryDb.insertWordsSync(dbWords);
|
DictionaryDb.insertWordsSync(dbWords);
|
||||||
|
|
@ -200,12 +217,12 @@ public class DictionaryLoader {
|
||||||
|
|
||||||
if (totalWords > 0) {
|
if (totalWords > 0) {
|
||||||
int progress = (int) Math.floor(100.0 * line / totalWords);
|
int progress = (int) Math.floor(100.0 * line / totalWords);
|
||||||
sendProgressMessage(handler, language, progress, settings.getDictionaryImportProgressUpdateInterval());
|
sendProgressMessage(language, progress, settings.getDictionaryImportProgressUpdateInterval());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
br.close();
|
br.close();
|
||||||
sendProgressMessage(handler, language, 100, 0);
|
sendProgressMessage(language, 100, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -242,7 +259,14 @@ public class DictionaryLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void sendProgressMessage(Handler handler, Language language, int progress, int progressUpdateInterval) {
|
private void sendProgressMessage(Language language, int progress, int progressUpdateInterval) {
|
||||||
|
if (statusHandler == null) {
|
||||||
|
Logger.w(
|
||||||
|
"tt9/DictionaryLoader.sendProgressMessage",
|
||||||
|
"Cannot send progress without a status Handler. Ignoring message.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
if (now - lastProgressUpdate < progressUpdateInterval) {
|
if (now - lastProgressUpdate < progressUpdateInterval) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -252,32 +276,43 @@ public class DictionaryLoader {
|
||||||
|
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putInt("languageId", language.getId());
|
bundle.putInt("languageId", language.getId());
|
||||||
|
bundle.putLong("time", getImportTime());
|
||||||
bundle.putInt("progress", progress);
|
bundle.putInt("progress", progress);
|
||||||
bundle.putInt("currentFile", currentFile);
|
bundle.putInt("currentFile", currentFile);
|
||||||
Message msg = new Message();
|
Message msg = new Message();
|
||||||
msg.setData(bundle);
|
msg.setData(bundle);
|
||||||
handler.sendMessage(msg);
|
statusHandler.sendMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void sendError(Handler handler, String message, int langId) {
|
private void sendError(String message, int langId) {
|
||||||
|
if (statusHandler == null) {
|
||||||
|
Logger.w("tt9/DictionaryLoader.sendError", "Cannot send an error without a status Handler. Ignoring message.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString("error", message);
|
bundle.putString("error", message);
|
||||||
bundle.putInt("languageId", langId);
|
bundle.putInt("languageId", langId);
|
||||||
Message msg = new Message();
|
Message msg = new Message();
|
||||||
msg.setData(bundle);
|
msg.setData(bundle);
|
||||||
handler.sendMessage(msg);
|
statusHandler.sendMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void sendImportError(Handler handler, String message, int langId, long fileLine, String word) {
|
private void sendImportError(String message, int langId, long fileLine, String word) {
|
||||||
|
if (statusHandler == null) {
|
||||||
|
Logger.w("tt9/DictionaryLoader.sendError", "Cannot send an import error without a status Handler. Ignoring message.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString("error", message);
|
bundle.putString("error", message);
|
||||||
bundle.putLong("fileLine", fileLine);
|
bundle.putLong("fileLine", fileLine + 1);
|
||||||
bundle.putInt("languageId", langId);
|
bundle.putInt("languageId", langId);
|
||||||
bundle.putString("word", word);
|
bundle.putString("word", word);
|
||||||
Message msg = new Message();
|
Message msg = new Message();
|
||||||
msg.setData(bundle);
|
msg.setData(bundle);
|
||||||
handler.sendMessage(msg);
|
statusHandler.sendMessage(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,10 @@ public class InputModeValidator {
|
||||||
return inputMode;
|
return inputMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputMode newMode = InputMode.getInstance(allowedModes.size() > 0 ? allowedModes.get(0) : InputMode.MODE_123);
|
InputMode newMode = InputMode.getInstance(
|
||||||
|
settings,
|
||||||
|
allowedModes.size() > 0 ? allowedModes.get(0) : InputMode.MODE_123
|
||||||
|
);
|
||||||
settings.saveInputMode(newMode);
|
settings.saveInputMode(newMode);
|
||||||
|
|
||||||
if (newMode.getId() != inputMode.getId()) {
|
if (newMode.getId() != inputMode.getId()) {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.Logger;
|
||||||
|
import io.github.sspanak.tt9.db.DictionaryDb;
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||||
|
|
@ -43,7 +44,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
private void loadSettings() {
|
private void loadSettings() {
|
||||||
mLanguage = LanguageCollection.getLanguage(settings.getInputLanguage());
|
mLanguage = LanguageCollection.getLanguage(settings.getInputLanguage());
|
||||||
mEnabledLanguages = settings.getEnabledLanguageIds();
|
mEnabledLanguages = settings.getEnabledLanguageIds();
|
||||||
mInputMode = InputMode.getInstance(settings.getInputMode());
|
mInputMode = InputMode.getInstance(settings, settings.getInputMode());
|
||||||
mInputMode.setTextCase(settings.getTextCase());
|
mInputMode.setTextCase(settings.getTextCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,12 +65,14 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
protected void onInit() {
|
protected void onInit() {
|
||||||
self = this;
|
self = this;
|
||||||
|
|
||||||
|
DictionaryDb.init(this);
|
||||||
|
|
||||||
if (softKeyHandler == null) {
|
if (softKeyHandler == null) {
|
||||||
softKeyHandler = new SoftKeyHandler(this);
|
softKeyHandler = new SoftKeyHandler(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSuggestionView == null) {
|
if (mSuggestionView == null) {
|
||||||
mSuggestionView = new SuggestionsView(softKeyHandler.getView());
|
mSuggestionView = new SuggestionsView(settings, softKeyHandler.getView());
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
@ -446,7 +449,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
private void nextInputMode() {
|
private void nextInputMode() {
|
||||||
if (mEditing == EDITING_STRICT_NUMERIC || mEditing == EDITING_DIALER) {
|
if (mEditing == EDITING_STRICT_NUMERIC || mEditing == EDITING_DIALER) {
|
||||||
clearSuggestions();
|
clearSuggestions();
|
||||||
mInputMode = InputMode.getInstance(InputMode.MODE_123);
|
mInputMode = InputMode.getInstance(settings, InputMode.MODE_123);
|
||||||
}
|
}
|
||||||
// when typing a word or viewing scrolling the suggestions, only change the case
|
// when typing a word or viewing scrolling the suggestions, only change the case
|
||||||
else if (!isSuggestionViewHidden()) {
|
else if (!isSuggestionViewHidden()) {
|
||||||
|
|
@ -459,7 +462,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
mInputMode.setTextCase(InputMode.CASE_UPPER);
|
mInputMode.setTextCase(InputMode.CASE_UPPER);
|
||||||
} else {
|
} else {
|
||||||
int modeIndex = (allowedInputModes.indexOf(mInputMode.getId()) + 1) % allowedInputModes.size();
|
int modeIndex = (allowedInputModes.indexOf(mInputMode.getId()) + 1) % allowedInputModes.size();
|
||||||
mInputMode = InputMode.getInstance(allowedInputModes.get(modeIndex));
|
mInputMode = InputMode.getInstance(settings, allowedInputModes.get(modeIndex));
|
||||||
|
|
||||||
mInputMode.defaultTextCase();
|
mInputMode.defaultTextCase();
|
||||||
}
|
}
|
||||||
|
|
@ -509,11 +512,11 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
int lastInputModeId = settings.getInputMode();
|
int lastInputModeId = settings.getInputMode();
|
||||||
if (allowedInputModes.contains(lastInputModeId)) {
|
if (allowedInputModes.contains(lastInputModeId)) {
|
||||||
mInputMode = InputMode.getInstance(lastInputModeId);
|
mInputMode = InputMode.getInstance(settings, lastInputModeId);
|
||||||
} else if (allowedInputModes.contains(InputMode.MODE_ABC)) {
|
} else if (allowedInputModes.contains(InputMode.MODE_ABC)) {
|
||||||
mInputMode = InputMode.getInstance(InputMode.MODE_ABC);
|
mInputMode = InputMode.getInstance(settings, InputMode.MODE_ABC);
|
||||||
} else {
|
} else {
|
||||||
mInputMode = InputMode.getInstance(allowedInputModes.get(0));
|
mInputMode = InputMode.getInstance(settings, allowedInputModes.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InputFieldHelper.isDialerField(inputField)) {
|
if (InputFieldHelper.isDialerField(inputField)) {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.Logger;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
abstract public class InputMode {
|
abstract public class InputMode {
|
||||||
// typing mode
|
// typing mode
|
||||||
|
|
@ -26,10 +27,10 @@ abstract public class InputMode {
|
||||||
protected String word = null;
|
protected String word = null;
|
||||||
|
|
||||||
|
|
||||||
public static InputMode getInstance(int mode) {
|
public static InputMode getInstance(SettingsStore settings, int mode) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case MODE_PREDICTIVE:
|
case MODE_PREDICTIVE:
|
||||||
return new ModePredictive();
|
return new ModePredictive(settings);
|
||||||
case MODE_ABC:
|
case MODE_ABC:
|
||||||
return new ModeABC();
|
return new ModeABC();
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ import io.github.sspanak.tt9.languages.Punctuation;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||||
|
|
||||||
public class ModePredictive extends InputMode {
|
public class ModePredictive extends InputMode {
|
||||||
|
private final SettingsStore settings;
|
||||||
|
|
||||||
public int getId() { return MODE_PREDICTIVE; }
|
public int getId() { return MODE_PREDICTIVE; }
|
||||||
|
|
||||||
private boolean isEmoji = false;
|
private boolean isEmoji = false;
|
||||||
|
|
@ -32,7 +34,8 @@ public class ModePredictive extends InputMode {
|
||||||
private final Pattern endOfSentence = Pattern.compile("(?<!\\.)[.?!]\\s*$");
|
private final Pattern endOfSentence = Pattern.compile("(?<!\\.)[.?!]\\s*$");
|
||||||
|
|
||||||
|
|
||||||
ModePredictive() {
|
ModePredictive(SettingsStore settings) {
|
||||||
|
this.settings = settings;
|
||||||
allowedTextCases.add(CASE_LOWER);
|
allowedTextCases.add(CASE_LOWER);
|
||||||
allowedTextCases.add(CASE_CAPITALIZE);
|
allowedTextCases.add(CASE_CAPITALIZE);
|
||||||
allowedTextCases.add(CASE_UPPER);
|
allowedTextCases.add(CASE_UPPER);
|
||||||
|
|
@ -194,8 +197,8 @@ public class ModePredictive extends InputMode {
|
||||||
language,
|
language,
|
||||||
digitSequence,
|
digitSequence,
|
||||||
stem,
|
stem,
|
||||||
SettingsStore.getInstance().getSuggestionsMin(),
|
settings.getSuggestionsMin(),
|
||||||
SettingsStore.getInstance().getSuggestionsMax()
|
settings.getSuggestionsMax()
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -22,19 +22,25 @@ public class ItemLoadDictionary extends ItemClickable {
|
||||||
public static final String NAME = "dictionary_load";
|
public static final String NAME = "dictionary_load";
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
private final SettingsStore settings;
|
||||||
private final DictionaryLoader loader;
|
private final DictionaryLoader loader;
|
||||||
private final DictionaryLoadingBar progressBar;
|
private final DictionaryLoadingBar progressBar;
|
||||||
|
|
||||||
|
|
||||||
ItemLoadDictionary(Preference item, Context context, DictionaryLoader loader, DictionaryLoadingBar progressBar) {
|
ItemLoadDictionary(Preference item, Context context, SettingsStore settings, DictionaryLoader loader, DictionaryLoadingBar progressBar) {
|
||||||
super(item);
|
super(item);
|
||||||
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
this.progressBar = progressBar;
|
this.progressBar = progressBar;
|
||||||
|
this.settings = settings;
|
||||||
|
|
||||||
|
loader.setStatusHandler(onDictionaryLoading);
|
||||||
|
|
||||||
if (!progressBar.isCompleted() && !progressBar.isFailed()) {
|
if (!progressBar.isCompleted() && !progressBar.isFailed()) {
|
||||||
changeToCancelButton();
|
changeToCancelButton();
|
||||||
|
} else {
|
||||||
|
changeToLoadButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,6 +49,7 @@ public class ItemLoadDictionary extends ItemClickable {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
progressBar.show(msg.getData());
|
progressBar.show(msg.getData());
|
||||||
|
item.setSummary(progressBar.getTitle() + " " + progressBar.getMessage());
|
||||||
|
|
||||||
if (progressBar.isCompleted()) {
|
if (progressBar.isCompleted()) {
|
||||||
changeToLoadButton();
|
changeToLoadButton();
|
||||||
|
|
@ -57,11 +64,11 @@ public class ItemLoadDictionary extends ItemClickable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean onClick(Preference p) {
|
protected boolean onClick(Preference p) {
|
||||||
ArrayList<Language> languages = LanguageCollection.getAll(SettingsStore.getInstance().getEnabledLanguageIds());
|
ArrayList<Language> languages = LanguageCollection.getAll(settings.getEnabledLanguageIds());
|
||||||
progressBar.setFileCount(languages.size());
|
progressBar.setFileCount(languages.size());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
loader.load(onDictionaryLoading, languages);
|
loader.load(languages);
|
||||||
changeToCancelButton();
|
changeToCancelButton();
|
||||||
} catch (DictionaryImportAlreadyRunningException e) {
|
} catch (DictionaryImportAlreadyRunningException e) {
|
||||||
loader.stop();
|
loader.stop();
|
||||||
|
|
@ -79,5 +86,6 @@ public class ItemLoadDictionary extends ItemClickable {
|
||||||
|
|
||||||
public void changeToLoadButton() {
|
public void changeToLoadButton() {
|
||||||
item.setTitle(context.getString(R.string.dictionary_load_title));
|
item.setTitle(context.getString(R.string.dictionary_load_title));
|
||||||
|
item.setSummary(progressBar.isFailed() ? progressBar.getMessage() : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ public class ItemResetKeys extends ItemClickable {
|
||||||
private final SettingsStore settings;
|
private final SettingsStore settings;
|
||||||
|
|
||||||
|
|
||||||
ItemResetKeys(Preference item, Context context, SectionKeymap dropdowns, SettingsStore settings) {
|
ItemResetKeys(Preference item, Context context, SettingsStore settings, SectionKeymap dropdowns) {
|
||||||
super(item);
|
super(item);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.dropdowns = dropdowns;
|
this.dropdowns = dropdowns;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
import androidx.appcompat.app.AppCompatDelegate;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
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.db.DictionaryLoader;
|
||||||
import io.github.sspanak.tt9.ui.DictionaryLoadingBar;
|
import io.github.sspanak.tt9.ui.DictionaryLoadingBar;
|
||||||
|
|
||||||
|
|
@ -17,7 +18,9 @@ public class PreferencesActivity extends AppCompatActivity {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
settings = new SettingsStore(this);
|
settings = new SettingsStore(this);
|
||||||
|
DictionaryDb.init(this);
|
||||||
|
|
||||||
|
validateFunctionKeys();
|
||||||
applyTheme();
|
applyTheme();
|
||||||
buildScreen();
|
buildScreen();
|
||||||
}
|
}
|
||||||
|
|
@ -39,6 +42,13 @@ public class PreferencesActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void validateFunctionKeys() {
|
||||||
|
if (!settings.areFunctionKeysSet()) {
|
||||||
|
settings.setDefaultKeys();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DictionaryLoadingBar getDictionaryProgressBar() {
|
DictionaryLoadingBar getDictionaryProgressBar() {
|
||||||
return DictionaryLoadingBar.getInstance(this);
|
return DictionaryLoadingBar.getInstance(this);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
||||||
ItemLoadDictionary loadItem = new ItemLoadDictionary(
|
ItemLoadDictionary loadItem = new ItemLoadDictionary(
|
||||||
findPreference(ItemLoadDictionary.NAME),
|
findPreference(ItemLoadDictionary.NAME),
|
||||||
activity,
|
activity,
|
||||||
|
activity.settings,
|
||||||
activity.getDictionaryLoader(),
|
activity.getDictionaryLoader(),
|
||||||
activity.getDictionaryProgressBar()
|
activity.getDictionaryProgressBar()
|
||||||
);
|
);
|
||||||
|
|
@ -94,7 +95,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
||||||
SectionKeymap section = new SectionKeymap(Arrays.asList(dropDowns), activity, activity.settings);
|
SectionKeymap section = new SectionKeymap(Arrays.asList(dropDowns), activity, activity.settings);
|
||||||
section.populate().activate();
|
section.populate().activate();
|
||||||
|
|
||||||
(new ItemResetKeys(findPreference(ItemResetKeys.NAME), activity, section, activity.settings))
|
(new ItemResetKeys(findPreference(ItemResetKeys.NAME), activity, activity.settings, section))
|
||||||
.enableClickHandler();
|
.enableClickHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,11 @@ import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.Logger;
|
||||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||||
|
|
||||||
|
|
||||||
public class SettingsStore {
|
public class SettingsStore {
|
||||||
private static SettingsStore self;
|
|
||||||
|
|
||||||
private final SharedPreferences prefs;
|
private final SharedPreferences prefs;
|
||||||
private final SharedPreferences.Editor prefsEditor;
|
private final SharedPreferences.Editor prefsEditor;
|
||||||
|
|
@ -31,15 +29,6 @@ public class SettingsStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static SettingsStore getInstance() {
|
|
||||||
if (self == null) {
|
|
||||||
self = new SettingsStore(TraditionalT9.getMainContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/************* validators *************/
|
/************* validators *************/
|
||||||
|
|
||||||
private boolean doesLanguageExist(int langId) {
|
private boolean doesLanguageExist(int langId) {
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,15 @@ public class AddWordAct extends AppCompatActivity {
|
||||||
|
|
||||||
private View main;
|
private View main;
|
||||||
private int lang;
|
private int lang;
|
||||||
|
private SettingsStore settings;
|
||||||
private String word;
|
private String word;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedData) {
|
protected void onCreate(Bundle savedData) {
|
||||||
|
settings = new SettingsStore(this);
|
||||||
|
|
||||||
AppCompatDelegate.setDefaultNightMode(
|
AppCompatDelegate.setDefaultNightMode(
|
||||||
SettingsStore.getInstance().getDarkTheme() ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO
|
settings.getDarkTheme() ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO
|
||||||
);
|
);
|
||||||
|
|
||||||
super.onCreate(savedData);
|
super.onCreate(savedData);
|
||||||
|
|
@ -53,7 +56,7 @@ public class AddWordAct extends AppCompatActivity {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case 0:
|
case 0:
|
||||||
Logger.d("onAddedWord", "Added word: '" + word + "'...");
|
Logger.d("onAddedWord", "Added word: '" + word + "'...");
|
||||||
SettingsStore.getInstance().saveLastWord(word);
|
settings.saveLastWord(word);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import androidx.core.app.NotificationCompat;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.DictionaryImportException;
|
import io.github.sspanak.tt9.db.DictionaryImportException;
|
||||||
|
|
@ -30,9 +31,11 @@ public class DictionaryLoadingBar {
|
||||||
private final NotificationCompat.Builder notificationBuilder;
|
private final NotificationCompat.Builder notificationBuilder;
|
||||||
private final Resources resources;
|
private final Resources resources;
|
||||||
|
|
||||||
|
private boolean hasFailed = false;
|
||||||
private int maxProgress = 0;
|
private int maxProgress = 0;
|
||||||
private int progress = 0;
|
private int progress = 0;
|
||||||
private boolean hasFailed = false;
|
private String title = "";
|
||||||
|
private String message = "";
|
||||||
|
|
||||||
|
|
||||||
public static DictionaryLoadingBar getInstance(Context context) {
|
public static DictionaryLoadingBar getInstance(Context context) {
|
||||||
|
|
@ -52,7 +55,7 @@ public class DictionaryLoadingBar {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
manager.createNotificationChannel(new NotificationChannel(
|
manager.createNotificationChannel(new NotificationChannel(
|
||||||
NOTIFICATION_CHANNEL_ID,
|
NOTIFICATION_CHANNEL_ID,
|
||||||
"Dictionary Loading Channel",
|
"Dictionary Status",
|
||||||
NotificationManager.IMPORTANCE_LOW
|
NotificationManager.IMPORTANCE_LOW
|
||||||
));
|
));
|
||||||
notificationBuilder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
|
notificationBuilder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
|
||||||
|
|
@ -83,6 +86,16 @@ public class DictionaryLoadingBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void show(Bundle data) {
|
public void show(Bundle data) {
|
||||||
String error = data.getString("error", null);
|
String error = data.getString("error", null);
|
||||||
|
|
||||||
|
|
@ -97,6 +110,7 @@ public class DictionaryLoadingBar {
|
||||||
} else {
|
} else {
|
||||||
hasFailed = false;
|
hasFailed = false;
|
||||||
showProgress(
|
showProgress(
|
||||||
|
data.getLong("time", 0),
|
||||||
data.getInt("currentFile", 0),
|
data.getInt("currentFile", 0),
|
||||||
data.getInt("progress", 0),
|
data.getInt("progress", 0),
|
||||||
data.getInt("languageId", -1)
|
data.getInt("languageId", -1)
|
||||||
|
|
@ -116,32 +130,31 @@ public class DictionaryLoadingBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void showProgress(int currentFile, int currentFileProgress, int languageId) {
|
private void showProgress(long time, int currentFile, int currentFileProgress, int languageId) {
|
||||||
progress = 100 * currentFile + currentFileProgress;
|
|
||||||
|
|
||||||
if (currentFileProgress < 0) {
|
if (currentFileProgress < 0) {
|
||||||
hide();
|
hide();
|
||||||
} else if (progress >= maxProgress) {
|
return;
|
||||||
renderProgress(
|
|
||||||
generateTitle(-1),
|
|
||||||
resources.getString(R.string.completed),
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
renderProgress(
|
|
||||||
generateTitle(languageId),
|
|
||||||
currentFileProgress + "%",
|
|
||||||
progress,
|
|
||||||
maxProgress
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progress = 100 * currentFile + currentFileProgress;
|
||||||
|
|
||||||
|
if (progress >= maxProgress) {
|
||||||
|
progress = maxProgress = 0;
|
||||||
|
title = generateTitle(-1);
|
||||||
|
|
||||||
|
String timeFormat = time > 60000 ? " (%1.0fs)" : " (%1.1fs)";
|
||||||
|
message = resources.getString(R.string.completed) + String.format(Locale.ENGLISH, timeFormat, time / 1000.0);
|
||||||
|
} else {
|
||||||
|
title = generateTitle(languageId);
|
||||||
|
message = currentFileProgress + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
renderProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void showError(String errorType, int langId, long line, String word) {
|
private void showError(String errorType, int langId, long line, String word) {
|
||||||
Language lang = LanguageCollection.getLanguage(langId);
|
Language lang = LanguageCollection.getLanguage(langId);
|
||||||
String message;
|
|
||||||
|
|
||||||
if (lang == null || errorType.equals(InvalidLanguageException.class.getSimpleName())) {
|
if (lang == null || errorType.equals(InvalidLanguageException.class.getSimpleName())) {
|
||||||
message = resources.getString(R.string.add_word_invalid_language);
|
message = resources.getString(R.string.add_word_invalid_language);
|
||||||
|
|
@ -156,16 +169,20 @@ public class DictionaryLoadingBar {
|
||||||
message = resources.getString(R.string.dictionary_load_error, languageName, errorType);
|
message = resources.getString(R.string.dictionary_load_error, languageName, errorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderError(generateTitle(-1), message);
|
title = generateTitle(-1);
|
||||||
|
progress = maxProgress = 0;
|
||||||
|
|
||||||
|
renderError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void hide() {
|
private void hide() {
|
||||||
|
progress = maxProgress = 0;
|
||||||
manager.cancel(NOTIFICATION_ID);
|
manager.cancel(NOTIFICATION_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void renderError(String title, String message) {
|
private void renderError() {
|
||||||
NotificationCompat.BigTextStyle bigMessage = new NotificationCompat.BigTextStyle();
|
NotificationCompat.BigTextStyle bigMessage = new NotificationCompat.BigTextStyle();
|
||||||
bigMessage.setBigContentTitle(title);
|
bigMessage.setBigContentTitle(title);
|
||||||
bigMessage.bigText(message);
|
bigMessage.bigText(message);
|
||||||
|
|
@ -174,16 +191,16 @@ public class DictionaryLoadingBar {
|
||||||
.setSmallIcon(android.R.drawable.stat_notify_error)
|
.setSmallIcon(android.R.drawable.stat_notify_error)
|
||||||
.setStyle(bigMessage)
|
.setStyle(bigMessage)
|
||||||
.setOngoing(false)
|
.setOngoing(false)
|
||||||
.setProgress(0, 0, false);
|
.setProgress(maxProgress, progress, false);
|
||||||
|
|
||||||
manager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
manager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void renderProgress(String title, String message, int progress, int maxProgress) {
|
private void renderProgress() {
|
||||||
notificationBuilder
|
notificationBuilder
|
||||||
.setSmallIcon(progress < maxProgress ? android.R.drawable.stat_notify_sync : R.drawable.ic_done)
|
.setSmallIcon(isCompleted() ? R.drawable.ic_done : android.R.drawable.stat_notify_sync)
|
||||||
.setOngoing(progress < maxProgress)
|
.setOngoing(!isCompleted())
|
||||||
.setProgress(maxProgress, progress, false)
|
.setProgress(maxProgress, progress, false)
|
||||||
.setContentTitle(title)
|
.setContentTitle(title)
|
||||||
.setContentText(message);
|
.setContentText(message);
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,15 @@ public class SuggestionsView {
|
||||||
protected int selectedIndex = 0;
|
protected int selectedIndex = 0;
|
||||||
|
|
||||||
private final RecyclerView mView;
|
private final RecyclerView mView;
|
||||||
|
private final SettingsStore settings;
|
||||||
private SuggestionsAdapter mSuggestionsAdapter;
|
private SuggestionsAdapter mSuggestionsAdapter;
|
||||||
|
|
||||||
|
|
||||||
public SuggestionsView(View mainView) {
|
public SuggestionsView(SettingsStore settings, View mainView) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.settings = settings;
|
||||||
|
|
||||||
mView = mainView.findViewById(R.id.main_suggestions_list);
|
mView = mainView.findViewById(R.id.main_suggestions_list);
|
||||||
mView.setLayoutManager(new LinearLayoutManager(mainView.getContext(), RecyclerView.HORIZONTAL,false));
|
mView.setLayoutManager(new LinearLayoutManager(mainView.getContext(), RecyclerView.HORIZONTAL,false));
|
||||||
|
|
||||||
|
|
@ -40,8 +43,8 @@ public class SuggestionsView {
|
||||||
private void configureAnimation() {
|
private void configureAnimation() {
|
||||||
DefaultItemAnimator animator = new DefaultItemAnimator();
|
DefaultItemAnimator animator = new DefaultItemAnimator();
|
||||||
|
|
||||||
int translateDuration = SettingsStore.getInstance().getSuggestionTranslateAnimationDuration();
|
int translateDuration = settings.getSuggestionTranslateAnimationDuration();
|
||||||
int selectDuration = SettingsStore.getInstance().getSuggestionSelectAnimationDuration();
|
int selectDuration = settings.getSuggestionSelectAnimationDuration();
|
||||||
|
|
||||||
animator.setMoveDuration(selectDuration);
|
animator.setMoveDuration(selectDuration);
|
||||||
animator.setChangeDuration(translateDuration);
|
animator.setChangeDuration(translateDuration);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue