Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@
import java.util.function.Consumer;

abstract public class AbstractFileProcessor {
protected Runnable cancelHandler;
protected Runnable failureHandler;
protected Runnable startHandler;
protected Consumer<String> successHandler;

private Thread processThread;
protected String statusMessage = "";

public boolean isCanceled() {
return processThread != null && processThread.isInterrupted();
}

public boolean isRunning() {
return processThread != null && processThread.isAlive();
}
Expand All @@ -22,6 +27,12 @@ public String getStatusMessage() {
return statusMessage;
}

protected void sendCancel() {
if (cancelHandler != null) {
cancelHandler.run();
}
}

protected void sendFailure() {
if (failureHandler != null) {
failureHandler.run();
Expand All @@ -35,6 +46,10 @@ protected void sendStart(@NonNull String message) {
}
}

public void setCancelHandler(Runnable handler) {
cancelHandler = handler;
}

public void setFailureHandler(Runnable handler) {
failureHandler = handler;
}
Expand All @@ -47,6 +62,12 @@ public void setSuccessHandler(Consumer<String> handler) {
successHandler = handler;
}

public void cancel() {
if (isRunning()) {
processThread.interrupt();
}
}

public boolean run(@NonNull Activity activity) {
if (isRunning()) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@
public class CustomWordsImporter extends AbstractFileProcessor {
private static CustomWordsImporter self;

private Consumer<Integer> progressHandler;
private Consumer<Float> progressHandler;
private Consumer<String> failureHandler;

private CustomWordFile file;
private final Resources resources;
private SQLiteOpener sqlite;

private long lastProgressUpdate = 0;
private int maxFileLines;
private int maxWords;


public static CustomWordsImporter getInstance(Context context) {
Expand All @@ -49,13 +51,14 @@ private CustomWordsImporter(Context context) {


public void clearAllHandlers() {
cancelHandler = null;
failureHandler = null;
progressHandler = null;
successHandler = null;
}


public void setProgressHandler(Consumer<Integer> handler) {
public void setProgressHandler(Consumer<Float> handler) {
progressHandler = handler;
}

Expand All @@ -65,7 +68,7 @@ public void setFailureHandler(Consumer<String> handler) {
}


private void sendProgress(int progress) {
private void sendProgress(float progress) {
long now = System.currentTimeMillis();
if (lastProgressUpdate + SettingsStore.DICTIONARY_IMPORT_PROGRESS_UPDATE_TIME < now) {
progressHandler.accept(progress);
Expand All @@ -91,8 +94,10 @@ private void sendFailure(String errorMessage) {
}


public void run(@NonNull Activity activity, @NonNull CustomWordFile file) {
public void run(@NonNull Activity activity, @NonNull SettingsStore settings, @NonNull CustomWordFile file) {
this.file = file;
this.maxFileLines = settings.getImportWordsMaxFileLines();
this.maxWords = settings.getImportWordsMaxWords();
super.run(activity);
}

Expand All @@ -102,9 +107,14 @@ protected void runSync(Activity activity) {
Timer.start(getClass().getSimpleName());

sendStart(resources.getString(R.string.dictionary_import_running));
if (isFileValid() && isThereRoomForMoreWords(activity) && insertWords()) {
sendSuccess();
Logger.i(getClass().getSimpleName(), "Imported " + file.getName() + " in " + Timer.get(getClass().getSimpleName()) + " ms");
if (isFileValid() && isThereRoomForMoreWords(activity) && isLineCountValid() && insertWords()) {
if (isCanceled()) {
sendCancel();
Logger.i(getClass().getSimpleName(), "Importing cancelled after " + Timer.get(getClass().getSimpleName()) + " ms");
} else {
sendSuccess();
Logger.i(getClass().getSimpleName(), "Imported " + file.getName() + " in " + Timer.get(getClass().getSimpleName()) + " ms");
}
} else {
Logger.e(getClass().getSimpleName(), "Failed to import " + file.getName());
}
Expand Down Expand Up @@ -132,9 +142,9 @@ private boolean insertWords() {
sqlite.beginTransaction();

for (String line; (line = reader.readLine()) != null; lineCount++) {
if (!isLineCountValid(lineCount)) {
if (isCanceled()) {
sqlite.failTransaction();
return false;
return true;
}

CustomWord customWord = createCustomWord(line, lineCount);
Expand All @@ -150,7 +160,7 @@ private boolean insertWords() {
}

if (file.getSize() > 20) {
sendProgress(lineCount * 100 / file.getSize());
sendProgress(lineCount * 100f / file.getSize());
}
}

Expand Down Expand Up @@ -189,7 +199,7 @@ private boolean isThereRoomForMoreWords(Context context) {
return false;
}

if ((new ReadOps()).countCustomWords(sqlite.getDb()) > SettingsStore.CUSTOM_WORDS_MAX) {
if ((new ReadOps()).countCustomWords(sqlite.getDb()) > maxWords) {
sendFailure(resources.getString(R.string.dictionary_import_error_too_many_words));
return false;
}
Expand All @@ -198,13 +208,20 @@ private boolean isThereRoomForMoreWords(Context context) {
}


private boolean isLineCountValid(int lineCount) {
if (lineCount <= SettingsStore.CUSTOM_WORDS_IMPORT_MAX_LINES) {
return true;
private boolean isLineCountValid() {
final int lines = file.getSize();

if (lines < 0) {
sendFailure(resources.getString(R.string.dictionary_import_error_cannot_read_file));
return false;
}

sendFailure(resources.getString(R.string.dictionary_import_error_file_too_long, SettingsStore.CUSTOM_WORDS_IMPORT_MAX_LINES));
return false;
if (lines > maxFileLines) {
sendFailure(resources.getString(R.string.dictionary_import_error_file_too_long, maxFileLines));
return false;
}

return true;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import androidx.activity.result.ActivityResultLauncher;
import androidx.preference.Preference;

import java.util.Locale;

import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.db.customWords.CustomWordsImporter;
import io.github.sspanak.tt9.db.entities.CustomWordFile;
Expand All @@ -20,6 +22,7 @@ public class ItemImportCustomWords extends ItemProcessCustomWordsAbstract {

private ActivityResultLauncher<Intent> importCustomWordsLauncher;
private String lastError;
private float lastProgress;

public ItemImportCustomWords(Preference item, PreferencesActivity activity, Runnable onStart, Runnable onFinish) {
super(item, activity, onStart, onFinish);
Expand All @@ -34,22 +37,43 @@ protected CustomWordsImporter getProcessor() {
@Override
protected boolean onClick(Preference p) {
setDefaultHandlers();
getProcessor().setCancelHandler(this::onCancel);
getProcessor().setFailureHandler(this::onFailure);
getProcessor().setProgressHandler(this::onProgress);
browseFiles();

if (getProcessor().isRunning()) {
getProcessor().cancel();
} else {
browseFiles();
}
return true;
}

@Override
protected boolean onStartProcessing() {
lastError = "";
lastProgress = 0;
return false;
}

private void onProgress(int progress) {
String loadingMsg = activity.getString(R.string.dictionary_import_progress, progress + "%");
private void onCancel() {
activity.runOnUiThread(() -> {
final String statusMsg = activity.getString(R.string.dictionary_import_canceled);

setAndNotifyReady();
DictionaryProgressNotification.getInstance(activity).showMessage("", statusMsg, statusMsg);

item.setTitle(R.string.dictionary_import_custom_words);
item.setSummary(statusMsg);
});
}

DictionaryProgressNotification.getInstance(activity).showLoadingMessage(loadingMsg, "", progress, 100);
private void onProgress(float progress) {
final String numberFormat = (progress - lastProgress) < 2 ? "%1.3f%%" : "%1.0f%%";
final String loadingMsg = activity.getString(R.string.dictionary_import_progress, String.format(Locale.getDefault(), numberFormat, progress));
lastProgress = progress;

DictionaryProgressNotification.getInstance(activity).showLoadingMessage(loadingMsg, "", Math.round(progress), 100);
activity.runOnUiThread(() -> item.setSummary(loadingMsg));
}

Expand Down Expand Up @@ -84,6 +108,15 @@ public void enable() {
super.enable();
}

@Override
public void disable() {
if (getProcessor().isRunning()) {
item.setTitle(R.string.dictionary_import_cancel);
} else {
super.disable();
}
}

void setBrowseFilesLauncher(ActivityResultLauncher<Intent> launcher) {
if (item != null) {
item.setEnabled(true);
Expand Down Expand Up @@ -122,6 +155,6 @@ void onFileSelected(ActivityResult result) {
return;
}

getProcessor().run(activity, file);
getProcessor().run(activity, activity.getSettings(), file);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.preferences.settings.SettingsStore;

public class AddWordsWithoutConfirmationSwitch extends SwitchPreferenceCompat {
public class SwitchAddWordsWithoutConfirmation extends SwitchPreferenceCompat {
public static final String NAME = "add_word_no_confirmation";

public AddWordsWithoutConfirmationSwitch(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
public SwitchAddWordsWithoutConfirmation(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}

public AddWordsWithoutConfirmationSwitch(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
public SwitchAddWordsWithoutConfirmation(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}

public AddWordsWithoutConfirmationSwitch(@NonNull Context context, @Nullable AttributeSet attrs) {
public SwitchAddWordsWithoutConfirmation(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}

public AddWordsWithoutConfirmationSwitch(@NonNull Context context) {
public SwitchAddWordsWithoutConfirmation(@NonNull Context context) {
super(context);
init(context);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.github.sspanak.tt9.preferences.screens.languages;

import android.content.Context;
import android.util.AttributeSet;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.SwitchPreferenceCompat;

import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.preferences.settings.SettingsAddedWords;

public class SwitchRaiseImportLimits extends SwitchPreferenceCompat {
public static final String NAME = "pref_raise_custom_words_import_limits";
public static final boolean DEFAULT = false;

public SwitchRaiseImportLimits(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context); }
public SwitchRaiseImportLimits(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); }
public SwitchRaiseImportLimits(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context); }
public SwitchRaiseImportLimits(@NonNull Context context) { super(context); init(context); }

private void init(@NonNull Context context) {
setKey(NAME);
setDefaultValue(DEFAULT);
setTitle(R.string.dictionary_import_raise_import_limits);
setSummary(context.getString(
R.string.dictionary_import_raise_import_limits_summary,
SettingsAddedWords.IMPORT_DEFAULT_MAX_FILE_LINES,
SettingsAddedWords.IMPORT_RAISED_MAX_FILE_LINES,
SettingsAddedWords.IMPORT_DEFAULT_MAX_WORDS,
SettingsAddedWords.IMPORT_RAISED_MAX_WORDS
));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.github.sspanak.tt9.preferences.settings;

import android.content.Context;

import io.github.sspanak.tt9.preferences.screens.languages.SwitchAddWordsWithoutConfirmation;
import io.github.sspanak.tt9.preferences.screens.languages.SwitchRaiseImportLimits;

public class SettingsAddedWords extends BaseSettings {
public final static int IMPORT_DEFAULT_MAX_FILE_LINES = 250;
public final static int IMPORT_DEFAULT_MAX_WORDS = 1000;
public final static int IMPORT_RAISED_MAX_FILE_LINES = 10_000;
public final static int IMPORT_RAISED_MAX_WORDS = 100_000;

SettingsAddedWords(Context context) {
super(context);
}

public boolean getAddWordsNoConfirmation() {
return prefs.getBoolean(SwitchAddWordsWithoutConfirmation.NAME, false);
}

public boolean getRaiseImportLimits() {
return prefs.getBoolean(SwitchRaiseImportLimits.NAME, SwitchRaiseImportLimits.DEFAULT);
}

public int getImportWordsMaxFileLines() {
return getRaiseImportLimits() ? IMPORT_RAISED_MAX_FILE_LINES : IMPORT_DEFAULT_MAX_FILE_LINES;
}

public int getImportWordsMaxWords() {
return getRaiseImportLimits() ? IMPORT_RAISED_MAX_WORDS : IMPORT_DEFAULT_MAX_WORDS;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import io.github.sspanak.tt9.util.Logger;
import io.github.sspanak.tt9.util.sys.DeviceInfo;

class SettingsHacks extends BaseSettings {
class SettingsHacks extends SettingsAddedWords {
public static final int COMPOSING_TEXT_RESTART_THRESHOLD = 150; // ms

private boolean demoMode = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ public class SettingsStatic extends SettingsColors {
public static final int BACKSPACE_ACCELERATION_MAX_CHARS_NO_SPACE = 4; // maximum chars to be deleted at once for languages with no spaces
public static final int BACKSPACE_ACCELERATION_REPEAT_DEBOUNCE = 5;
public final static int CLIPBOARD_PREVIEW_LENGTH = 20;
public final static int CUSTOM_WORDS_IMPORT_MAX_LINES = 250;
public final static int CUSTOM_WORDS_MAX = 1000;
public final static int CUSTOM_WORDS_SEARCH_RESULTS_MAX = 50;
public final static int DICTIONARY_AUTO_LOAD_COOLDOWN_TIME = 1200000; // 20 minutes in ms
public final static int DICTIONARY_DOWNLOAD_CONNECTION_TIMEOUT = 10000; // ms
Expand Down
Loading
Loading