1
0
Fork 0

dictionary loading progress is now displayed as a notification

This commit is contained in:
Dimo Karaivanov 2022-11-03 15:09:54 +02:00
parent 0126e3db64
commit b0c7f6b67f
17 changed files with 180 additions and 69 deletions

View file

@ -0,0 +1,7 @@
package io.github.sspanak.tt9.db;
public class DictionaryImportAlreadyRunningException extends Exception{
public DictionaryImportAlreadyRunningException() {
super("Dictionary import is already running.");
}
}

View file

@ -23,11 +23,12 @@ public class DictionaryLoader {
private final AssetManager assets;
private final T9Preferences prefs;
private boolean isStopped = true;
private final Pattern containsPunctuation = Pattern.compile("\\p{Punct}(?<!-)");
private Thread loadThread;
private int currentFile = 0;
private long lastProgressUpdate = 0;
private final Pattern containsPunctuation = Pattern.compile("\\p{Punct}(?<!-)");
public DictionaryLoader(Context context) {
assets = context.getAssets();
@ -35,27 +36,37 @@ public class DictionaryLoader {
}
public void load(Handler handler, ArrayList<Language> languages) {
new Thread() {
public void load(Handler handler, ArrayList<Language> languages) throws DictionaryImportAlreadyRunningException {
if (isRunning()) {
throw new DictionaryImportAlreadyRunningException();
}
loadThread = new Thread() {
@Override
public void run() {
currentFile = 0;
isStopped = false;
// SQLite does not support parallel queries, so let's import them one by one
for (Language lang : languages) {
if (isStopped) {
if (isInterrupted()) {
break;
}
importAll(handler, lang);
currentFile++;
}
}
}.start();
};
loadThread.start();
}
public void stop() {
isStopped = true;
loadThread.interrupt();
}
public boolean isRunning() {
return loadThread != null && loadThread.isAlive();
}
@ -160,9 +171,9 @@ public class DictionaryLoader {
sendProgressMessage(handler, language, 0, 0);
for (String word; (word = br.readLine()) != null; line++) {
if (isStopped) {
if (loadThread.isInterrupted()) {
br.close();
sendProgressMessage(handler, language, 0, 0);
sendProgressMessage(handler, language, -1, 0);
throw new DictionaryImportAbortedException();
}

View file

@ -162,7 +162,7 @@ public class T9Preferences {
/************* internal settings *************/
public int getDictionaryImportProgressUpdateInterval() { return 100; /* ms */ }
public int getDictionaryImportProgressUpdateInterval() { return 250; /* ms */ }
public int getDictionaryImportWordChunkSize() { return 1000; /* words */ }
public int getSuggestionsMax() { return 20; }
public int getSuggestionsMin() { return 8; }

View file

@ -0,0 +1,92 @@
package io.github.sspanak.tt9.ui;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.languages.Language;
import io.github.sspanak.tt9.languages.LanguageCollection;
public class DictionaryLoadingBar {
private static final int NOTIFICATION_ID = 1;
private static final String NOTIFICATION_CHANNEL_ID = "loading-notifications";
private final NotificationManager manager;
private final NotificationCompat.Builder notificationBuilder;
private final Resources resources;
private int maxProgress = 0;
DictionaryLoadingBar(Context context) {
resources = context.getResources();
manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
manager.createNotificationChannel(new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"Dictionary Loading Channel",
NotificationManager.IMPORTANCE_LOW
));
notificationBuilder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
} else {
notificationBuilder = new NotificationCompat.Builder(context);
}
notificationBuilder
.setSmallIcon(R.drawable.ic_notification)
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
.setOnlyAlertOnce(true);
}
private String generateTitle(int languageId) {
Language lang = LanguageCollection.getLanguage(languageId);
if (lang != null) {
return resources.getString(R.string.dictionary_loading, lang.getName());
}
return resources.getString(R.string.dictionary_load_title);
}
public void show(int currentFile, int currentFileProgress, int languageId) {
int totalProgress = 100 * currentFile + currentFileProgress;
if (currentFileProgress < 0) {
hide();
return;
} else if (totalProgress >= maxProgress) {
notificationBuilder
.setContentTitle(generateTitle(-1))
.setContentText(resources.getString(R.string.dictionary_loaded))
.setOngoing(false)
.setProgress(0, 0, false);
} else {
notificationBuilder
.setContentTitle(generateTitle(languageId))
.setContentText(currentFileProgress + "%")
.setOngoing(true)
.setProgress(maxProgress, totalProgress, false);
}
manager.notify(NOTIFICATION_ID, notificationBuilder.build());
}
public void hide() {
manager.cancel(NOTIFICATION_ID);
}
public void setFileCount(int count) {
maxProgress = count * 100;
}
}

View file

@ -2,7 +2,6 @@ package io.github.sspanak.tt9.ui;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -21,6 +20,7 @@ import java.util.ArrayList;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.db.DictionaryDb;
import io.github.sspanak.tt9.db.DictionaryImportAlreadyRunningException;
import io.github.sspanak.tt9.db.DictionaryImportException;
import io.github.sspanak.tt9.db.DictionaryLoader;
import io.github.sspanak.tt9.languages.InvalidLanguageCharactersException;
@ -35,7 +35,7 @@ import io.github.sspanak.tt9.settings_legacy.SettingAdapter;
public class TraditionalT9Settings extends ListActivity implements DialogInterface.OnCancelListener {
private DictionaryLoader loader;
ProgressDialog progressDialog;
DictionaryLoadingBar progressBar;
Context mContext = null;
@ -43,8 +43,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// maybe need this?
// http://stackoverflow.com/questions/7645880/listview-with-onitemclicklistener-android
progressBar = new DictionaryLoadingBar(this);
// get settings
T9Preferences prefs = new T9Preferences(getApplicationContext());
@ -98,18 +97,22 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
}
private void truncateWords() {
Handler afterTruncate = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
UI.toast(mContext, R.string.dictionary_truncated);
}
};
DictionaryDb.truncateWords(afterTruncate);
if (loader != null && loader.isRunning()) {
loader.stop();
}
Handler afterTruncate = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
UI.toast(mContext, R.string.dictionary_truncated);
}
};
DictionaryDb.truncateWords(afterTruncate);
}
private void loadDictionaries() {
ArrayList<Language> languages = LanguageCollection.getAll(T9Preferences.getInstance().getEnabledLanguages());
initProgress(100 * languages.size());
progressBar.setFileCount(languages.size());
Handler loadHandler = new Handler(Looper.getMainLooper()) {
@Override
@ -117,7 +120,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
String error = msg.getData().getString("error", null);
if (error != null) {
hideProgress();
progressBar.hide();
handleError(
error,
msg.getData().getInt("languageId", -1),
@ -125,58 +128,24 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
msg.getData().getString("word", "")
);
} else {
int langId = msg.getData().getInt("languageId", -1);
Language lang = LanguageCollection.getLanguage(langId);
String langName = lang != null ? lang.getName() : "???";
String title = getResources().getString(R.string.dictionary_loading, langName);
showProgress(
progressBar.show(
msg.getData().getInt("currentFile", 0),
msg.getData().getInt("progress", 0),
title
msg.getData().getInt("languageId", -1)
);
}
}
};
loader = new DictionaryLoader(this);
loader.load(loadHandler, languages);
}
private void initProgress(int max) {
if (progressDialog == null) {
progressDialog = new ProgressDialog(this);
progressDialog.setOnCancelListener(TraditionalT9Settings.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
if (loader == null) {
loader = new DictionaryLoader(this);
}
progressDialog.setMax(max);
}
private void showProgress(int currentFile, int currentFileProgress, String title) {
if (progressDialog == null) {
return;
}
if (title != null) {
progressDialog.setMessage(title);
}
int totalProgress = 100 * currentFile + currentFileProgress;
if (totalProgress <= 0 || totalProgress >= progressDialog.getMax()) {
progressDialog.dismiss();
} else {
progressDialog.setProgress(totalProgress);
if (!progressDialog.isShowing()) {
progressDialog.show();
}
}
}
private void hideProgress() {
if (progressDialog != null) {
progressDialog.dismiss();
try {
loader.load(loadHandler, languages);
} catch (DictionaryImportAlreadyRunningException e) {
loader.stop();
UI.toast(this, getString(R.string.dictionary_import_cancelled));
}
}