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.Future;
|
||||
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.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.util.ConsumerCompat;
|
||||
import io.github.sspanak.tt9.util.Logger;
|
||||
import io.github.sspanak.tt9.util.Timer;
|
||||
|
||||
public class DataStore {
|
||||
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) {
|
||||
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) {
|
||||
if (!checkOrNotify()) {
|
||||
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) {
|
||||
if (language == null || language instanceof NullLanguage || !checkOrNotify()) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package io.github.sspanak.tt9.preferences.screens.languages;
|
|||
import androidx.preference.Preference;
|
||||
|
||||
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.preferences.PreferencesActivity;
|
||||
import io.github.sspanak.tt9.preferences.items.ItemClickable;
|
||||
|
|
@ -14,6 +14,7 @@ class ItemTruncateAll extends ItemClickable {
|
|||
public static final String NAME = "dictionary_truncate";
|
||||
|
||||
protected final PreferencesActivity activity;
|
||||
protected final DictionaryDeleter deleter;
|
||||
private final Runnable onStart;
|
||||
private final Runnable onFinish;
|
||||
|
||||
|
|
@ -21,31 +22,49 @@ class ItemTruncateAll extends ItemClickable {
|
|||
ItemTruncateAll(Preference item, PreferencesActivity activity, Runnable onStart, Runnable onFinish) {
|
||||
super(item);
|
||||
this.activity = activity;
|
||||
this.deleter = DictionaryDeleter.getInstance(activity);
|
||||
this.onStart = onStart;
|
||||
this.onFinish = onFinish;
|
||||
|
||||
refreshStatus();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean onClick(Preference p) {
|
||||
onStartDeleting();
|
||||
DataStore.deleteLanguages(this::onFinishDeleting, LanguageCollection.getAll(false));
|
||||
onStart.run();
|
||||
setBusy();
|
||||
deleter.deleteLanguages(LanguageCollection.getAll(false));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected void onStartDeleting() {
|
||||
onStart.run();
|
||||
disable();
|
||||
void refreshStatus() {
|
||||
if (deleter.isRunning()) {
|
||||
setBusy();
|
||||
} else {
|
||||
enable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void setBusy() {
|
||||
deleter.setOnFinish(this::onFinishDeleting);
|
||||
item.setSummary(R.string.dictionary_truncating);
|
||||
disable();
|
||||
}
|
||||
|
||||
|
||||
public void enable() {
|
||||
super.enable();
|
||||
item.setSummary("");
|
||||
}
|
||||
|
||||
|
||||
protected void onFinishDeleting() {
|
||||
activity.runOnUiThread(() -> {
|
||||
onFinish.run();
|
||||
item.setSummary("");
|
||||
enable();
|
||||
UI.toastFromAsync(activity, R.string.dictionary_truncated);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import java.util.ArrayList;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import io.github.sspanak.tt9.db.DataStore;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||
|
|
@ -31,8 +30,9 @@ class ItemTruncateUnselected extends ItemTruncateAll {
|
|||
}
|
||||
}
|
||||
|
||||
onStartDeleting();
|
||||
DataStore.deleteLanguages(this::onFinishDeleting, unselectedLanguages);
|
||||
setBusy();
|
||||
deleter.setOnFinish(this::onFinishDeleting);
|
||||
deleter.deleteLanguages(unselectedLanguages);
|
||||
|
||||
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.CustomWordsImporter;
|
||||
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.preferences.PreferencesActivity;
|
||||
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 static final String NAME = "Languages";
|
||||
|
||||
private final ArrayList<ItemClickable> clickables = new ArrayList<>();
|
||||
private static final ArrayList<ItemClickable> clickables = new ArrayList<>();
|
||||
|
||||
private ItemLoadDictionary loadItem;
|
||||
private ItemImportCustomWords importCustomWordsItem;
|
||||
private ItemExportDictionary exportDictionaryItem;
|
||||
private ItemExportCustomWords exportCustomWordsItem;
|
||||
private ItemTruncateAll truncateAllItem;
|
||||
private ItemTruncateUnselected truncateUnselectedItem;
|
||||
|
||||
public LanguagesScreen() { init(); }
|
||||
public LanguagesScreen(PreferencesActivity activity) { init(activity); }
|
||||
|
|
@ -56,22 +59,25 @@ public class LanguagesScreen extends BaseScreenFragment {
|
|||
this::onActionFinish
|
||||
);
|
||||
|
||||
clickables.add(loadItem);
|
||||
clickables.add(exportDictionaryItem);
|
||||
|
||||
clickables.add(new ItemTruncateUnselected(
|
||||
truncateUnselectedItem = new ItemTruncateUnselected(
|
||||
findPreference(ItemTruncateUnselected.NAME),
|
||||
activity,
|
||||
this::onActionStart,
|
||||
this::onActionFinish
|
||||
));
|
||||
);
|
||||
|
||||
clickables.add(new ItemTruncateAll(
|
||||
truncateAllItem = new ItemTruncateAll(
|
||||
findPreference(ItemTruncateAll.NAME),
|
||||
activity,
|
||||
this::onActionStart,
|
||||
this::onActionFinish
|
||||
));
|
||||
);
|
||||
|
||||
clickables.clear();
|
||||
clickables.add(loadItem);
|
||||
clickables.add(exportDictionaryItem);
|
||||
clickables.add(truncateUnselectedItem);
|
||||
clickables.add(truncateAllItem);
|
||||
|
||||
clickables.add(new ItemDeleteCustomWords(findPreference(ItemDeleteCustomWords.NAME)));
|
||||
|
||||
|
|
@ -112,6 +118,8 @@ public class LanguagesScreen extends BaseScreenFragment {
|
|||
exportDictionaryItem.refreshStatus();
|
||||
exportCustomWordsItem.refreshStatus();
|
||||
importCustomWordsItem.refreshStatus();
|
||||
truncateUnselectedItem.refreshStatus();
|
||||
truncateAllItem.refreshStatus();
|
||||
|
||||
if (DictionaryLoader.getInstance(activity).isRunning()) {
|
||||
loadItem.refreshStatus();
|
||||
|
|
@ -120,6 +128,7 @@ public class LanguagesScreen extends BaseScreenFragment {
|
|||
CustomWordsExporter.getInstance().isRunning()
|
||||
|| DictionaryExporter.getInstance().isRunning()
|
||||
|| CustomWordsImporter.getInstance(activity).isRunning()
|
||||
|| DictionaryDeleter.getInstance(activity).isRunning()
|
||||
) {
|
||||
onActionStart();
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue