fixed the delete dictionary buttons not staying locked when navigating from and to the Languages screen, while deletion is in progress
This commit is contained in:
parent
fec7d62168
commit
f7e11c7445
7 changed files with 152 additions and 59 deletions
|
|
@ -11,7 +11,6 @@ import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import io.github.sspanak.tt9.db.entities.AddWordResult;
|
import io.github.sspanak.tt9.db.entities.AddWordResult;
|
||||||
import io.github.sspanak.tt9.db.wordPairs.WordPairStore;
|
import io.github.sspanak.tt9.db.wordPairs.WordPairStore;
|
||||||
|
|
@ -21,7 +20,6 @@ import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
import io.github.sspanak.tt9.util.ConsumerCompat;
|
import io.github.sspanak.tt9.util.ConsumerCompat;
|
||||||
import io.github.sspanak.tt9.util.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
import io.github.sspanak.tt9.util.Timer;
|
|
||||||
|
|
||||||
public class DataStore {
|
public class DataStore {
|
||||||
private final static String LOG_TAG = DataStore.class.getSimpleName();
|
private final static String LOG_TAG = DataStore.class.getSimpleName();
|
||||||
|
|
@ -80,27 +78,6 @@ public class DataStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void deleteLanguages(Runnable notification, @NonNull ArrayList<Language> languages) {
|
|
||||||
Timer.start(LOG_TAG);
|
|
||||||
|
|
||||||
AtomicInteger progress = new AtomicInteger(languages.size());
|
|
||||||
Runnable onDeleted = () -> {
|
|
||||||
if (progress.decrementAndGet() == 0) {
|
|
||||||
Logger.d(LOG_TAG, "Deleted " + languages.size() + " languages. Time: " + Timer.stop(LOG_TAG) + " ms");
|
|
||||||
notification.run();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (Language language : languages) {
|
|
||||||
runInTransaction(
|
|
||||||
() -> { words.remove(language); pairs.remove(language); },
|
|
||||||
onDeleted,
|
|
||||||
"Failed deleting languages."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void put(ConsumerCompat<AddWordResult> statusHandler, Language language, String word) {
|
public static void put(ConsumerCompat<AddWordResult> statusHandler, Language language, String word) {
|
||||||
runInThread(() -> statusHandler.accept(words.put(language, word)));
|
runInThread(() -> statusHandler.accept(words.put(language, word)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,17 +165,6 @@ public class WordPairStore extends BaseSyncStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void remove(@NonNull Language language) {
|
|
||||||
if (!checkOrNotify()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteOps.deleteWordPairs(sqlite.getDb(), language.getId());
|
|
||||||
slowestLoadTime = 0;
|
|
||||||
slowestSaveTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void remove(@NonNull ArrayList<Language> languages) {
|
public void remove(@NonNull ArrayList<Language> languages) {
|
||||||
if (!checkOrNotify()) {
|
if (!checkOrNotify()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
package io.github.sspanak.tt9.db.words;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.db.BaseSyncStore;
|
||||||
|
import io.github.sspanak.tt9.db.sqlite.DeleteOps;
|
||||||
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
|
import io.github.sspanak.tt9.languages.NaturalLanguage;
|
||||||
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
import io.github.sspanak.tt9.util.Timer;
|
||||||
|
|
||||||
|
public class DictionaryDeleter extends BaseSyncStore {
|
||||||
|
private static final String LOG_TAG = DictionaryDeleter.class.getSimpleName();
|
||||||
|
private static DictionaryDeleter self;
|
||||||
|
|
||||||
|
@NonNull private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
|
@Nullable Future<?> deleteTask;
|
||||||
|
@Nullable private Runnable notification;
|
||||||
|
|
||||||
|
|
||||||
|
protected DictionaryDeleter(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static DictionaryDeleter getInstance(Context context) {
|
||||||
|
if (self == null) {
|
||||||
|
self = new DictionaryDeleter(context);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void deleteLanguages(@NonNull ArrayList<Language> languages) {
|
||||||
|
if (!checkOrNotify()) {
|
||||||
|
onFinish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer.start(LOG_TAG);
|
||||||
|
deleteTask = executor.submit(() -> deleteLanguagesSync(languages));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void deleteLanguagesSync(@NonNull ArrayList<Language> languages) {
|
||||||
|
for (Language language : languages) {
|
||||||
|
if (!deleteLanguage(language)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteTask = null;
|
||||||
|
|
||||||
|
if (notification != null) {
|
||||||
|
notification.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.d(LOG_TAG, "Deleted " + languages.size() + " languages. Time: " + Timer.stop(LOG_TAG) + " ms");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean deleteLanguage(Language language) {
|
||||||
|
if (!(language instanceof NaturalLanguage)) {
|
||||||
|
Logger.w(LOG_TAG, "Invalid language type to delete: " + language.getClass().getSimpleName() + ". Skipping.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
sqlite.beginTransaction();
|
||||||
|
DeleteOps.delete(sqlite.getDb(), language.getId());
|
||||||
|
DeleteOps.deleteWordPairs(sqlite.getDb(), language.getId());
|
||||||
|
sqlite.finishTransaction();
|
||||||
|
} catch (Exception e) {
|
||||||
|
sqlite.failTransaction();
|
||||||
|
Logger.e(LOG_TAG, "Failed deleting language: " + language.getId() + ". " + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void onFinish() {
|
||||||
|
if (notification != null) {
|
||||||
|
notification.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isRunning() {
|
||||||
|
return deleteTask != null && !deleteTask.isDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setOnFinish(Runnable notification) {
|
||||||
|
this.notification = notification;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -118,13 +118,6 @@ public class WordStore extends BaseSyncStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void remove(Language language) {
|
|
||||||
if (checkOrNotify() && readOps.exists(sqlite.getDb(), language.getId())) {
|
|
||||||
DeleteOps.delete(sqlite.getDb(), language.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void removeCustomWord(Language language, String word) {
|
public void removeCustomWord(Language language, String word) {
|
||||||
if (language == null || language instanceof NullLanguage || !checkOrNotify()) {
|
if (language == null || language instanceof NullLanguage || !checkOrNotify()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package io.github.sspanak.tt9.preferences.screens.languages;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.DataStore;
|
import io.github.sspanak.tt9.db.words.DictionaryDeleter;
|
||||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||||
import io.github.sspanak.tt9.preferences.items.ItemClickable;
|
import io.github.sspanak.tt9.preferences.items.ItemClickable;
|
||||||
|
|
@ -14,6 +14,7 @@ class ItemTruncateAll extends ItemClickable {
|
||||||
public static final String NAME = "dictionary_truncate";
|
public static final String NAME = "dictionary_truncate";
|
||||||
|
|
||||||
protected final PreferencesActivity activity;
|
protected final PreferencesActivity activity;
|
||||||
|
protected final DictionaryDeleter deleter;
|
||||||
private final Runnable onStart;
|
private final Runnable onStart;
|
||||||
private final Runnable onFinish;
|
private final Runnable onFinish;
|
||||||
|
|
||||||
|
|
@ -21,31 +22,49 @@ class ItemTruncateAll extends ItemClickable {
|
||||||
ItemTruncateAll(Preference item, PreferencesActivity activity, Runnable onStart, Runnable onFinish) {
|
ItemTruncateAll(Preference item, PreferencesActivity activity, Runnable onStart, Runnable onFinish) {
|
||||||
super(item);
|
super(item);
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
|
this.deleter = DictionaryDeleter.getInstance(activity);
|
||||||
this.onStart = onStart;
|
this.onStart = onStart;
|
||||||
this.onFinish = onFinish;
|
this.onFinish = onFinish;
|
||||||
|
|
||||||
|
refreshStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean onClick(Preference p) {
|
protected boolean onClick(Preference p) {
|
||||||
onStartDeleting();
|
onStart.run();
|
||||||
DataStore.deleteLanguages(this::onFinishDeleting, LanguageCollection.getAll(false));
|
setBusy();
|
||||||
|
deleter.deleteLanguages(LanguageCollection.getAll(false));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void onStartDeleting() {
|
void refreshStatus() {
|
||||||
onStart.run();
|
if (deleter.isRunning()) {
|
||||||
disable();
|
setBusy();
|
||||||
|
} else {
|
||||||
|
enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void setBusy() {
|
||||||
|
deleter.setOnFinish(this::onFinishDeleting);
|
||||||
item.setSummary(R.string.dictionary_truncating);
|
item.setSummary(R.string.dictionary_truncating);
|
||||||
|
disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void enable() {
|
||||||
|
super.enable();
|
||||||
|
item.setSummary("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void onFinishDeleting() {
|
protected void onFinishDeleting() {
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
onFinish.run();
|
onFinish.run();
|
||||||
item.setSummary("");
|
|
||||||
enable();
|
enable();
|
||||||
UI.toastFromAsync(activity, R.string.dictionary_truncated);
|
UI.toastFromAsync(activity, R.string.dictionary_truncated);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.db.DataStore;
|
|
||||||
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;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||||
|
|
@ -31,8 +30,9 @@ class ItemTruncateUnselected extends ItemTruncateAll {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onStartDeleting();
|
setBusy();
|
||||||
DataStore.deleteLanguages(this::onFinishDeleting, unselectedLanguages);
|
deleter.setOnFinish(this::onFinishDeleting);
|
||||||
|
deleter.deleteLanguages(unselectedLanguages);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.customWords.CustomWordsExporter;
|
import io.github.sspanak.tt9.db.customWords.CustomWordsExporter;
|
||||||
import io.github.sspanak.tt9.db.customWords.CustomWordsImporter;
|
import io.github.sspanak.tt9.db.customWords.CustomWordsImporter;
|
||||||
import io.github.sspanak.tt9.db.customWords.DictionaryExporter;
|
import io.github.sspanak.tt9.db.customWords.DictionaryExporter;
|
||||||
|
import io.github.sspanak.tt9.db.words.DictionaryDeleter;
|
||||||
import io.github.sspanak.tt9.db.words.DictionaryLoader;
|
import io.github.sspanak.tt9.db.words.DictionaryLoader;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||||
import io.github.sspanak.tt9.preferences.items.ItemClickable;
|
import io.github.sspanak.tt9.preferences.items.ItemClickable;
|
||||||
|
|
@ -19,12 +20,14 @@ import io.github.sspanak.tt9.preferences.screens.BaseScreenFragment;
|
||||||
public class LanguagesScreen extends BaseScreenFragment {
|
public class LanguagesScreen extends BaseScreenFragment {
|
||||||
public static final String NAME = "Languages";
|
public static final String NAME = "Languages";
|
||||||
|
|
||||||
private final ArrayList<ItemClickable> clickables = new ArrayList<>();
|
private static final ArrayList<ItemClickable> clickables = new ArrayList<>();
|
||||||
|
|
||||||
private ItemLoadDictionary loadItem;
|
private ItemLoadDictionary loadItem;
|
||||||
private ItemImportCustomWords importCustomWordsItem;
|
private ItemImportCustomWords importCustomWordsItem;
|
||||||
private ItemExportDictionary exportDictionaryItem;
|
private ItemExportDictionary exportDictionaryItem;
|
||||||
private ItemExportCustomWords exportCustomWordsItem;
|
private ItemExportCustomWords exportCustomWordsItem;
|
||||||
|
private ItemTruncateAll truncateAllItem;
|
||||||
|
private ItemTruncateUnselected truncateUnselectedItem;
|
||||||
|
|
||||||
public LanguagesScreen() { init(); }
|
public LanguagesScreen() { init(); }
|
||||||
public LanguagesScreen(PreferencesActivity activity) { init(activity); }
|
public LanguagesScreen(PreferencesActivity activity) { init(activity); }
|
||||||
|
|
@ -56,22 +59,25 @@ public class LanguagesScreen extends BaseScreenFragment {
|
||||||
this::onActionFinish
|
this::onActionFinish
|
||||||
);
|
);
|
||||||
|
|
||||||
clickables.add(loadItem);
|
truncateUnselectedItem = new ItemTruncateUnselected(
|
||||||
clickables.add(exportDictionaryItem);
|
|
||||||
|
|
||||||
clickables.add(new ItemTruncateUnselected(
|
|
||||||
findPreference(ItemTruncateUnselected.NAME),
|
findPreference(ItemTruncateUnselected.NAME),
|
||||||
activity,
|
activity,
|
||||||
this::onActionStart,
|
this::onActionStart,
|
||||||
this::onActionFinish
|
this::onActionFinish
|
||||||
));
|
);
|
||||||
|
|
||||||
clickables.add(new ItemTruncateAll(
|
truncateAllItem = new ItemTruncateAll(
|
||||||
findPreference(ItemTruncateAll.NAME),
|
findPreference(ItemTruncateAll.NAME),
|
||||||
activity,
|
activity,
|
||||||
this::onActionStart,
|
this::onActionStart,
|
||||||
this::onActionFinish
|
this::onActionFinish
|
||||||
));
|
);
|
||||||
|
|
||||||
|
clickables.clear();
|
||||||
|
clickables.add(loadItem);
|
||||||
|
clickables.add(exportDictionaryItem);
|
||||||
|
clickables.add(truncateUnselectedItem);
|
||||||
|
clickables.add(truncateAllItem);
|
||||||
|
|
||||||
clickables.add(new ItemDeleteCustomWords(findPreference(ItemDeleteCustomWords.NAME)));
|
clickables.add(new ItemDeleteCustomWords(findPreference(ItemDeleteCustomWords.NAME)));
|
||||||
|
|
||||||
|
|
@ -112,6 +118,8 @@ public class LanguagesScreen extends BaseScreenFragment {
|
||||||
exportDictionaryItem.refreshStatus();
|
exportDictionaryItem.refreshStatus();
|
||||||
exportCustomWordsItem.refreshStatus();
|
exportCustomWordsItem.refreshStatus();
|
||||||
importCustomWordsItem.refreshStatus();
|
importCustomWordsItem.refreshStatus();
|
||||||
|
truncateUnselectedItem.refreshStatus();
|
||||||
|
truncateAllItem.refreshStatus();
|
||||||
|
|
||||||
if (DictionaryLoader.getInstance(activity).isRunning()) {
|
if (DictionaryLoader.getInstance(activity).isRunning()) {
|
||||||
loadItem.refreshStatus();
|
loadItem.refreshStatus();
|
||||||
|
|
@ -120,6 +128,7 @@ public class LanguagesScreen extends BaseScreenFragment {
|
||||||
CustomWordsExporter.getInstance().isRunning()
|
CustomWordsExporter.getInstance().isRunning()
|
||||||
|| DictionaryExporter.getInstance().isRunning()
|
|| DictionaryExporter.getInstance().isRunning()
|
||||||
|| CustomWordsImporter.getInstance(activity).isRunning()
|
|| CustomWordsImporter.getInstance(activity).isRunning()
|
||||||
|
|| DictionaryDeleter.getInstance(activity).isRunning()
|
||||||
) {
|
) {
|
||||||
onActionStart();
|
onActionStart();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue