1
0
Fork 0

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:
sspanak 2022-11-25 10:31:15 +02:00 committed by Dimo Karaivanov
parent b550d5d5dd
commit a6fa129984
14 changed files with 171 additions and 89 deletions

View file

@ -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;
} }

View file

@ -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);
} }
} }

View file

@ -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()) {

View file

@ -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)) {

View file

@ -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:

View file

@ -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;

View file

@ -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() : "");
} }
} }

View file

@ -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;

View file

@ -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);
} }

View file

@ -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();
} }

View file

@ -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) {

View file

@ -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:

View file

@ -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);

View file

@ -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);