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,19 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF">
<group android:scaleX="0.12126316"
android:scaleY="0.12126316"
android:translateX="0.96"
android:translateY="1.5217317">
<group android:translateY="135.80667">
<path android:pathData="M82.375,-85.03125Q76.609375,-90.359375,70.140625,-90.359375L50.546875,-90.359375L50.546875,-13.84375Q50.546875,-9.953125,51.40625,-6.421875Q52.28125,-2.890625,54.296875,-0L30.8125,-0Q34.28125,-6.046875,34.28125,-13.84375L34.28125,-90.359375L12.96875,-90.359375Q8.5,-90.359375,3.171875,-85.03125L3.171875,-103L82.375,-103L82.375,-85.03125Z"
android:fillColor="#000000"/>
<path android:pathData="M109.1875,-71.90625Q109.1875,-66.21875,109.90625,-62.5625Q110.625,-58.90625,112.28125,-56.78125Q113.9375,-54.671875,116.453125,-53.9375Q118.984375,-53.203125,122.578125,-53.203125L166.35938,-53.203125L166.35938,-75.421875Q166.35938,-80.09375,165.48438,-83.234375Q164.625,-86.390625,162.46875,-88.28125Q160.3125,-90.1875,156.78125,-90.984375Q153.25,-91.796875,147.92188,-91.796875L124.015625,-91.796875Q119.984375,-91.796875,117.171875,-90.84375Q114.375,-89.890625,112.5625,-87.625Q110.765625,-85.359375,109.96875,-81.5625Q109.1875,-77.765625,109.1875,-71.90625ZM114.515625,-22.84375Q113.796875,-21.71875,113.578125,-20.71875Q113.359375,-19.71875,113.359375,-17.3125Q113.359375,-14.1875,116.09375,-12.6875Q118.828125,-11.203125,126.609375,-11.203125L149.35938,-11.203125Q159.15625,-11.203125,162.75,-15.03125Q166.35938,-18.875,166.35938,-27.09375L166.35938,-42L113.65625,-42Q107.3125,-42,103.421875,-42.859375Q99.53125,-43.734375,97.21875,-46.046875Q94.921875,-48.375,94.125,-52.4375Q93.34375,-56.515625,93.34375,-62.90625L93.34375,-81.078125Q93.34375,-87.90625,94.203125,-92.1875Q95.078125,-96.46875,97.65625,-98.859375Q100.25,-101.265625,105.140625,-102.125Q110.046875,-103,118.109375,-103L157.57812,-103Q165.92188,-103,170.8125,-102.28125Q175.71875,-101.5625,178.3125,-99.390625Q180.90625,-97.234375,181.625,-93.484375Q182.34375,-89.75,182.34375,-83.703125L182.34375,-19.296875Q182.34375,-13.25,181.54688,-9.5Q180.76562,-5.765625,178.09375,-3.671875Q175.4375,-1.578125,170.3125,-0.78125Q165.20312,0,156.5625,0L114.65625,0Q109.046875,0,105.375,-0.84375Q101.703125,-1.703125,99.609375,-3.34375Q97.515625,-5,96.71875,-7.5625Q95.9375,-10.140625,95.9375,-13.578125Q95.9375,-17.28125,95.5,-19.203125Q95.078125,-21.140625,93.921875,-22.84375L114.515625,-22.84375Z"
android:fillColor="#000000"/>
</group>
</group>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

View file

@ -18,10 +18,13 @@
<string name="pref_truncatedict">Изтрий речник</string>
<string name="dictionary_import_bad_char">Неуспешно зареждане. Невалидна дума \"%1$s\" на ред %2$d за език \"%3$s\".</string>
<string name="dictionary_import_cancelled">Зареждането на речник е отменено.</string>
<string name="dictionary_import_error">Несупешно зареждане на речник за език \"%1$s\" (%2$s).</string>
<string name="dictionary_loaded">Готово</string>
<string name="dictionary_loading">Зареждане на речник (%1$s)…</string>
<string name="dictionary_loading_user_dict">Зареждане на вашия речник…</string>
<string name="dictionary_load_title">Зареждане на речник</string>
<string name="dictionary_not_found">Неуспешно зареждане. Липсва речник за \"%1$s\".</string>
<string name="dictionary_truncated">Речникът е изтрит успешно</string>
<string name="dictionary_truncated">Речникът е изтрит успешно.</string>
</resources>

View file

@ -17,6 +17,8 @@
<string name="pref_truncatedict">Supprimer le dictionaire</string>
<string name="dictionary_import_error">Echec du chargement de dictionnaire pour langue «%1$s» (%2$s).</string>
<string name="dictionary_import_cancelled">Chargement du dictionnaire annulée.</string>
<string name="dictionary_loaded">Terminé</string>
<string name="dictionary_loading">Chargement du dictionnaire (%1$s)…</string>
<string name="dictionary_loading_user_dict">Chargement du dictionnaire utilisateur…</string>
<string name="dictionary_load_title">Charger le dictionnaire</string>

View file

@ -16,6 +16,8 @@
<string name="pref_loaduserdict">Carica dizionario utente</string>
<string name="pref_truncatedict">Eliminare il dizionario</string>
<string name="dictionary_import_cancelled">Caricamento dizionario annullato.</string>
<string name="dictionary_loaded">Terminato</string>
<string name="dictionary_loading">Caricamento dizionario (%1$s)…</string>
<string name="dictionary_loading_user_dict">Caricamento dizionario utente…</string>
<string name="dictionary_load_title">Caricamento dizionario</string>

View file

@ -15,7 +15,7 @@
<string name="pref_loaddict">Woordenboek laden</string>
<string name="pref_loaduserdict">Gebruikerswoordenboek laden</string>
<string name="pref_truncatedict">Woordenboek wissen</string>
<string name="dictionary_loading">Woordenboek laden…</string>
<string name="dictionary_loading">Woordenboek laden (%1$s)</string>
<string name="dictionary_loading_user_dict">Gebruikerswoordenboek laden…</string>
<string name="dictionary_load_title">Woordenboek laden</string>
<string name="dictionary_not_found">Laden mislukt. Woordenboek voor %1$s niet gevonden.</string>

View file

@ -17,7 +17,9 @@
<string name="pref_loaduserdict">Загрузить свой словарь</string>
<string name="pref_truncatedict">Очистить словарь</string>
<string name="dictionary_import_cancelled">Загрузка словаря отменена.</string>
<string name="dictionary_import_error">Ошибка загрузки словаря для языка «%1$s» (%2$s).</string>
<string name="dictionary_loaded">Завершена</string>
<string name="dictionary_loading">Загрузка словаря (%1$s)…</string>
<string name="dictionary_loading_user_dict">Загрузка пользовательского словаря…</string>
<string name="dictionary_load_title">Загрузить словарь</string>

View file

@ -16,7 +16,9 @@
<string name="pref_loaduserdict">Завантажити свій словник</string>
<string name="pref_truncatedict">Очистити словник</string>
<string name="dictionary_import_cancelled">Завантаження словника скасовано.</string>
<string name="dictionary_import_error">Помилка завантаження словника для мови «%1$s» (%2$s).</string>
<string name="dictionary_loaded">Завершено</string>
<string name="dictionary_loading">Завантаження словника (%1$s)…</string>
<string name="dictionary_loading_user_dict">Завантаження словника користувача…</string>
<string name="dictionary_load_title">Завантажити словник</string>

View file

@ -22,7 +22,9 @@
<string name="pref_truncatedict">Clear dictionary</string>
<string name="dictionary_import_bad_char">Loading failed. Invalid word \"%1$s\" on line %2$d of language \"%3$s\".</string>
<string name="dictionary_import_cancelled">Dictionary import cancelled.</string>
<string name="dictionary_import_error">Failed importing dictionary for language \"%1$s\" (%2$s).</string>
<string name="dictionary_loaded">Done</string>
<string name="dictionary_loading">Loading dictionary (%1$s)…</string>
<string name="dictionary_loading_user_dict">Loading user dictionary…</string>
<string name="dictionary_load_title">Load dictionary</string>

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,6 +97,10 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
}
private void truncateWords() {
if (loader != null && loader.isRunning()) {
loader.stop();
}
Handler afterTruncate = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
@ -109,7 +112,7 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
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)
);
}
}
};
if (loader == null) {
loader = new DictionaryLoader(this);
}
try {
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);
}
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();
} catch (DictionaryImportAlreadyRunningException e) {
loader.stop();
UI.toast(this, getString(R.string.dictionary_import_cancelled));
}
}