diff --git a/app/build.gradle b/app/build.gradle index 8dcb5240..b19642f6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -103,8 +103,14 @@ android { flavorDimensions = ['app'] productFlavors { - full { dimension 'app' } - lite { dimension 'app' } + full { + dimension 'app' + buildConfigField 'Boolean', 'LITE', 'false' + } + lite { + dimension 'app' + buildConfigField 'Boolean', 'LITE', 'true' + } } applicationVariants.configureEach { variant -> diff --git a/app/dictionary-tools.gradle b/app/dictionary-tools.gradle index 57844f9b..2e139cbd 100644 --- a/app/dictionary-tools.gradle +++ b/app/dictionary-tools.gradle @@ -2,8 +2,9 @@ ext.getDictionaryProperties = { dictionariesDir, sizesDir -> fileTree(dir: dictionariesDir).getFiles().parallelStream().forEach {dictionary -> def hash = dictionary.exists() ? dictionary.text.digest("SHA-1") : "" def revision = dictionary.exists() ? exec("git log --pretty=tformat:%H -n 1 ${dictionary}") : "" + def size = dictionary.exists() ? dictionary.length() : 0 def words = dictionary.exists() ? dictionary.text.split("\n").length : 0 - new File(sizesDir, "${dictionary.getName()}.props.yml").text = "hash: ${hash}\nrevision: ${revision}\nwords: ${words}" + new File(sizesDir, "${dictionary.getName()}.props.yml").text = "hash: ${hash}\nrevision: ${revision}\nsize: ${size}\nwords: ${words}" } } \ No newline at end of file diff --git a/app/src/main/java/io/github/sspanak/tt9/db/WordStore.java b/app/src/main/java/io/github/sspanak/tt9/db/WordStore.java index a44461c5..081cb947 100644 --- a/app/src/main/java/io/github/sspanak/tt9/db/WordStore.java +++ b/app/src/main/java/io/github/sspanak/tt9/db/WordStore.java @@ -53,6 +53,26 @@ public class WordStore { } + /** + * Returns a list of the languages that are already loaded in the database. + */ + public ArrayList exists(ArrayList languages) { + ArrayList loadedLanguages = new ArrayList<>(); + + if (!checkOrNotify()) { + return loadedLanguages; + } + + for (Language language : languages) { + if (readOps.exists(sqlite.getDb(), language.getId())) { + loadedLanguages.add(language.getId()); + } + } + + return loadedLanguages; + } + + /** * Loads words matching and similar to a given digit sequence * For example: "7655" -> "roll" (exact match), but also: "rolled", "roller", "rolling", ... diff --git a/app/src/main/java/io/github/sspanak/tt9/db/WordStoreAsync.java b/app/src/main/java/io/github/sspanak/tt9/db/WordStoreAsync.java index 985ffc2b..010eb30c 100644 --- a/app/src/main/java/io/github/sspanak/tt9/db/WordStoreAsync.java +++ b/app/src/main/java/io/github/sspanak/tt9/db/WordStoreAsync.java @@ -79,4 +79,11 @@ public class WordStoreAsync { getStore().getSimilarCustom(language, wordFilter))) ).start(); } + + + public static void exists(ConsumerCompat> dataHandler, ArrayList languages) { + new Thread(() -> asyncHandler.post(() -> dataHandler.accept( + getStore().exists(languages)) + )).start(); + } } diff --git a/app/src/main/java/io/github/sspanak/tt9/db/entities/WordFile.java b/app/src/main/java/io/github/sspanak/tt9/db/entities/WordFile.java index e98c4c7d..6d974cfd 100644 --- a/app/src/main/java/io/github/sspanak/tt9/db/entities/WordFile.java +++ b/app/src/main/java/io/github/sspanak/tt9/db/entities/WordFile.java @@ -24,6 +24,7 @@ public class WordFile { private String hash = null; private String downloadUrl = null; private int totalLines = -1; + private long size = -1; public WordFile(Context context, String name, AssetManager assets) { @@ -151,6 +152,29 @@ public class WordFile { } + public long getSize() { + if (size < 0) { + loadProperties(); + } + + return size; + } + + + private void setSize(String rawProperty, String rawValue) { + if (!rawProperty.equals("size")) { + return; + } + + try { + size = Long.parseLong(rawValue); + } catch (Exception e) { + Logger.w(LOG_TAG, "Invalid 'size' property of: " + name + ". Expecting an integer, got: '" + rawValue + "'."); + size = 0; + } + } + + private void loadProperties() { String propertyFilename = name + ".props.yml"; @@ -164,6 +188,7 @@ public class WordFile { setDownloadUrl(parts[0], parts[1]); setHash(parts[0], parts[1]); setTotalLines(parts[0], parts[1]); + setSize(parts[0], parts[1]); } } catch (Exception e) { Logger.w(LOG_TAG, "Could not read the property file: " + propertyFilename + ". " + e.getMessage()); diff --git a/app/src/main/java/io/github/sspanak/tt9/languages/NaturalLanguage.java b/app/src/main/java/io/github/sspanak/tt9/languages/NaturalLanguage.java index 510b70c5..f217ce85 100644 --- a/app/src/main/java/io/github/sspanak/tt9/languages/NaturalLanguage.java +++ b/app/src/main/java/io/github/sspanak/tt9/languages/NaturalLanguage.java @@ -17,6 +17,7 @@ public class NaturalLanguage extends Language implements Comparable> layout = new ArrayList<>(); private final HashMap characterKeyMap = new HashMap<>(); @@ -183,6 +184,15 @@ public class NaturalLanguage extends Language implements Comparable 0) { + debouncer.removeCallbacksAndMessages(null); + debouncer.postDelayed(() -> onChange(s.toString()), debounceTime); + } else { + onChange(s.toString()); + } + } + + protected abstract void onChange(String word); +} diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/deleteWords/DeletableWordsList.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/deleteWords/DeletableWordsList.java index 59329405..6f4077ff 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/deleteWords/DeletableWordsList.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/deleteWords/DeletableWordsList.java @@ -41,7 +41,7 @@ class DeletableWordsList { void addNoResult(boolean noSearchTerm) { if (item != null) { Preference pref = new PreferencePlainText(item.getContext()); - pref.setSummary(noSearchTerm ? "--" : item.getContext().getString(R.string.delete_words_no_result)); + pref.setSummary(noSearchTerm ? "--" : item.getContext().getString(R.string.search_results_void)); item.addPreference(pref); } } diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/deleteWords/PreferenceSearchWords.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/deleteWords/PreferenceSearchWords.java index cd27e987..d701e261 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/deleteWords/PreferenceSearchWords.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/deleteWords/PreferenceSearchWords.java @@ -2,24 +2,21 @@ package io.github.sspanak.tt9.preferences.screens.deleteWords; import android.content.Context; import android.util.AttributeSet; -import android.widget.EditText; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.preference.PreferenceViewHolder; import java.util.ArrayList; -import io.github.sspanak.tt9.R; import io.github.sspanak.tt9.db.WordStoreAsync; import io.github.sspanak.tt9.languages.Language; import io.github.sspanak.tt9.languages.LanguageCollection; -import io.github.sspanak.tt9.preferences.custom.ScreenPreference; +import io.github.sspanak.tt9.preferences.items.ItemTextInput; import io.github.sspanak.tt9.preferences.settings.SettingsStore; import io.github.sspanak.tt9.util.ConsumerCompat; import io.github.sspanak.tt9.util.Logger; -public class PreferenceSearchWords extends ScreenPreference { +public class PreferenceSearchWords extends ItemTextInput { public static final String NAME = "dictionary_delete_words_search"; private static final String LOG_TAG = PreferenceSearchWords.class.getSimpleName(); @@ -33,28 +30,6 @@ public class PreferenceSearchWords extends ScreenPreference { public PreferenceSearchWords(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public PreferenceSearchWords(@NonNull Context context) { super(context); } - - @Override - public void onBindViewHolder(@NonNull PreferenceViewHolder holder) { - super.onBindViewHolder(holder); - EditText editText = holder.itemView.findViewById(R.id.input_text_input_field); - if (editText == null) { - Logger.e(LOG_TAG, "Cannot attach a text change listener. Unable to find the EditText element."); - } else { - editText.addTextChangedListener(TextChangeListener.getInstance(this::onChange)); - } - } - - - @Override protected int getDefaultLayout() { return R.layout.pref_input_text; } - @Override protected int getLargeLayout() { return R.layout.pref_input_text_large; } - - - @NonNull - public String getLastSearchTerm() { - return lastSearchTerm; - } - private SettingsStore getSettings() { if (settings == null) { settings = new SettingsStore(getContext()); @@ -64,7 +39,14 @@ public class PreferenceSearchWords extends ScreenPreference { } - private void onChange(String word) { + @NonNull + public String getLastSearchTerm() { + return lastSearchTerm; + } + + + @Override + protected void onChange(String word) { lastSearchTerm = word == null || word.trim().isEmpty() ? "" : word.trim(); if (onWords == null) { diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/deleteWords/TextChangeListener.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/deleteWords/TextChangeListener.java deleted file mode 100644 index 22e04459..00000000 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/deleteWords/TextChangeListener.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.sspanak.tt9.preferences.screens.deleteWords; - -import android.os.Handler; -import android.os.Looper; -import android.text.Editable; -import android.text.TextWatcher; - -import androidx.annotation.NonNull; - -import io.github.sspanak.tt9.preferences.settings.SettingsStore; -import io.github.sspanak.tt9.util.ConsumerCompat; - -class TextChangeListener implements TextWatcher { - private static TextChangeListener self; - - @NonNull private ConsumerCompat onChange; - @NonNull private final Handler debouncer = new Handler(Looper.getMainLooper()); - - private TextChangeListener(@NonNull ConsumerCompat onChange) { - this.onChange = onChange; - } - - static TextChangeListener getInstance(@NonNull ConsumerCompat onChange) { - if (self == null) { - self = new TextChangeListener(onChange); - } - - self.onChange = onChange; - return self; - } - - @Override public void afterTextChanged(Editable s) { - debouncer.removeCallbacksAndMessages(null); - debouncer.postDelayed(() -> onChange.accept(s.toString()), SettingsStore.DELETE_WORDS_SEARCH_DELAY); - } - - @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} -} diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languageSelection/LanguageSelectionScreen.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languageSelection/LanguageSelectionScreen.java new file mode 100644 index 00000000..610ba9c1 --- /dev/null +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languageSelection/LanguageSelectionScreen.java @@ -0,0 +1,97 @@ +package io.github.sspanak.tt9.preferences.screens.languageSelection; + +import androidx.annotation.NonNull; +import androidx.preference.PreferenceCategory; + +import java.util.ArrayList; + +import io.github.sspanak.tt9.R; +import io.github.sspanak.tt9.db.WordStoreAsync; +import io.github.sspanak.tt9.languages.Language; +import io.github.sspanak.tt9.languages.LanguageCollection; +import io.github.sspanak.tt9.languages.NaturalLanguage; +import io.github.sspanak.tt9.preferences.PreferencesActivity; +import io.github.sspanak.tt9.preferences.screens.BaseScreenFragment; + +public class LanguageSelectionScreen extends BaseScreenFragment { + public static final String NAME = "LanguageSelection"; + + private PreferenceCategory languagesCategory; + + public LanguageSelectionScreen() { init(); } + public LanguageSelectionScreen(PreferencesActivity activity) { init(activity); } + + + @Override public String getName() { return NAME; } + @Override protected int getTitle() { return R.string.language_selection_title; } + @Override protected int getXml() { return R.xml.prefs_screen_language_selection; } + + + @Override + protected void onCreate() { + createLanguageList(); + enableFiltering(); + resetFontSize(false); + } + + + private void createLanguageList() { + languagesCategory = findPreference("language_list"); + if (languagesCategory == null) { + return; + } + + ArrayList allLanguages = LanguageCollection.getAll(activity, true); + if (allLanguages.isEmpty()) { + return; + } + + addLanguagesToCategory(languagesCategory, allLanguages); + WordStoreAsync.exists(this::addLoadedStatus, allLanguages); + } + + + private void addLanguagesToCategory(@NonNull PreferenceCategory category, ArrayList allLanguages) { + ArrayList enabledLanguageIds = activity.getSettings().getEnabledLanguageIds(); + + PreferenceSwitchLanguage.clearItems(); + + for (Language language : allLanguages) { + if (language instanceof NaturalLanguage) { + PreferenceSwitchLanguage item = new PreferenceSwitchLanguage(activity, (NaturalLanguage) language); + category.addPreference(item); + + // Inflating sometimes resets the checked state to false for some reason. + // This is why we have to set it at the end. + // https://stackoverflow.com/q/42951557 + item.setChecked(enabledLanguageIds.contains(language.getId())); + } + } + } + + + private void addLoadedStatus(ArrayList enabledLanguageIds) { + if (languagesCategory == null) { + return; + } + + activity.runOnUiThread(() -> { + for (int languageId : enabledLanguageIds) { + PreferenceSwitchLanguage item = languagesCategory.findPreference(PreferenceSwitchLanguage.KEY_PREFIX + languageId); + if (item != null) { + item.setLoaded(); + } + } + }); + } + + + private void enableFiltering() { + PreferenceSearchLanguage search = findPreference("language_search"); + if (search != null) { + search + .setLanguageItems(PreferenceSwitchLanguage.getItems()) + .setNoResultItem(findPreference("language_search_no_result")); + } + } +} diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languageSelection/PreferenceSearchLanguage.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languageSelection/PreferenceSearchLanguage.java new file mode 100644 index 00000000..be171e96 --- /dev/null +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languageSelection/PreferenceSearchLanguage.java @@ -0,0 +1,71 @@ +package io.github.sspanak.tt9.preferences.screens.languageSelection; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.preference.Preference; + +import java.util.ArrayList; + +import io.github.sspanak.tt9.preferences.items.ItemTextInput; +import io.github.sspanak.tt9.util.Logger; + +public class PreferenceSearchLanguage extends ItemTextInput { + @NonNull private ArrayList languageItems = new ArrayList<>(); + private Preference noResultItem; + + public PreferenceSearchLanguage(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public PreferenceSearchLanguage(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public PreferenceSearchLanguage(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public PreferenceSearchLanguage(@NonNull Context context) { + super(context); + } + + private void showNoResultItem(boolean show) { + if (noResultItem != null) { + noResultItem.setVisible(show); + } + } + + @Override + protected void onChange(String word) { + word = word == null ? "" : word.trim(); + + int visibleLanguages = languageItems.size(); + for (PreferenceSwitchLanguage languageItem : languageItems) { + CharSequence title = languageItem.getTitle() == null ? "" : languageItem.getTitle(); + CharSequence summary = languageItem.getSummary() == null ? "" : languageItem.getSummary(); + + languageItem.setVisible( + title.toString().toLowerCase().startsWith(word.toLowerCase()) || + summary.toString().toLowerCase().startsWith(word.toLowerCase()) + ); + + if (!languageItem.isVisible()) { + visibleLanguages--; + } + } + + showNoResultItem(visibleLanguages == 0); + } + + PreferenceSearchLanguage setLanguageItems(@NonNull ArrayList languageItems) { + this.languageItems = languageItems; + return this; + } + + void setNoResultItem(Preference noResultItem) { + this.noResultItem = noResultItem; + } +} diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languageSelection/PreferenceSwitchLanguage.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languageSelection/PreferenceSwitchLanguage.java new file mode 100644 index 00000000..ccf12ae7 --- /dev/null +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languageSelection/PreferenceSwitchLanguage.java @@ -0,0 +1,106 @@ +package io.github.sspanak.tt9.preferences.screens.languageSelection; + +import android.app.Activity; +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.preference.Preference; +import androidx.preference.SwitchPreferenceCompat; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import io.github.sspanak.tt9.BuildConfig; +import io.github.sspanak.tt9.R; +import io.github.sspanak.tt9.db.entities.WordFile; +import io.github.sspanak.tt9.languages.NaturalLanguage; +import io.github.sspanak.tt9.preferences.PreferencesActivity; +import io.github.sspanak.tt9.preferences.settings.SettingsStore; + +public class PreferenceSwitchLanguage extends SwitchPreferenceCompat { + public static final String KEY_PREFIX = "language_"; + + private static final ArrayList items = new ArrayList<>(); + + public PreferenceSwitchLanguage(@NonNull PreferencesActivity activity, @NonNull NaturalLanguage language) { + super(activity); + + setKey(KEY_PREFIX + language.getId()); + setTitle(language.getName()); + setSummary(generateSummary(activity, language)); + setOnPreferenceChangeListener(PreferenceSwitchLanguage::handleChange); + items.add(this); + } + + + static void clearItems() { + items.clear(); + } + + static ArrayList getItems() { + return new ArrayList<>(items); + } + + + private String generateSummary(Activity activity, NaturalLanguage language) { + String summary = language.getLocale().getDisplayLanguage(); + + String wordsString = activity.getString(R.string.language_selection_words); + WordFile wordFile = new WordFile(activity, language.getDictionaryFile(), activity.getAssets()); + if (wordFile.getTotalLines() > 1000000) { + summary += String.format(", %1.2fM %s", wordFile.getTotalLines() / 1000000.0, wordsString); + } else { + summary += ", " + wordFile.getTotalLines() / 1000 + "k " + wordsString; + } + + if (BuildConfig.LITE) { + summary += String.format(", %1.2f Mb", wordFile.getSize() / 1048576.0); + } + + return summary; + } + + + private String getLanguageId() { + return getKey().substring(KEY_PREFIX.length()); + } + + + private static boolean handleChange(Preference p, Object newValue) { + SettingsStore settings = ((PreferencesActivity) p.getContext()).getSettings(); + String languageSettingsId = ((PreferenceSwitchLanguage) p).getLanguageId(); + + Set enabledLanguages = new HashSet<>(); + + for (PreferenceSwitchLanguage item : items) { + if (item.isChecked()) { + enabledLanguages.add(item.getLanguageId()); + } + } + + if ((boolean) newValue) { + enabledLanguages.add(languageSettingsId); + } else { + enabledLanguages.remove(languageSettingsId); + } + + settings.saveEnabledLanguageIds(enabledLanguages); + + return true; + } + + + void setLoaded() { + Context context = getContext(); + + String summary = getSummary() != null ? getSummary().toString() : null; + if (summary == null) { + return; + } + + summary += " " + context.getString(R.string.language_selection_language_loaded); + + setSummary(summary); + } +} diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemSelectLanguage.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemSelectLanguage.java index a27ca76c..9b9df945 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemSelectLanguage.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemSelectLanguage.java @@ -1,80 +1,32 @@ package io.github.sspanak.tt9.preferences.screens.languages; -import androidx.preference.MultiSelectListPreference; +import androidx.preference.Preference; -import java.util.ArrayList; -import java.util.HashSet; - -import io.github.sspanak.tt9.R; -import io.github.sspanak.tt9.languages.Language; import io.github.sspanak.tt9.languages.LanguageCollection; import io.github.sspanak.tt9.preferences.PreferencesActivity; -import io.github.sspanak.tt9.ui.UI; class ItemSelectLanguage { public static final String NAME = "pref_languages"; private final PreferencesActivity activity; - private final MultiSelectListPreference item; + private final Preference item; - ItemSelectLanguage(PreferencesActivity activity, MultiSelectListPreference multiSelect) { + ItemSelectLanguage(PreferencesActivity activity, Preference item) { this.activity = activity; - this.item = multiSelect; + this.item = item; } public ItemSelectLanguage populate() { - if (item == null) { - return this; - } - - ArrayList languages = LanguageCollection.getAll(activity, true); - if (languages.isEmpty()) { - UI.alert(activity, R.string.error, R.string.failed_loading_language_definitions); - // do not return, the MultiSelect component requires arrays, even if empty, otherwise it crashes - } - - ArrayList values = new ArrayList<>(); - for (Language l : languages) { - values.add(String.valueOf(l.getId())); - } - - ArrayList keys = new ArrayList<>(); - for (Language l : languages) { - keys.add(l.getName()); - } - - item.setEntries(keys.toArray(new CharSequence[0])); - item.setEntryValues(values.toArray(new CharSequence[0])); - item.setValues(activity.getSettings().getEnabledLanguagesIdsAsStrings()); previewSelection(); - return this; } - public void enableValidation() { + private void previewSelection() { if (item == null) { return; } - item.setOnPreferenceChangeListener((preference, newValue) -> { - @SuppressWarnings("unchecked") HashSet newLanguages = (HashSet) newValue; - if (newLanguages.isEmpty()) { - newLanguages.add("1"); - } - - activity.getSettings().saveEnabledLanguageIds(newLanguages); - item.setValues(activity.getSettings().getEnabledLanguagesIdsAsStrings()); - previewSelection(); - - // we validate and save manually above, so "false" disables automatic save - return false; - }); - - } - - - private void previewSelection() { item.setSummary( LanguageCollection.toString(LanguageCollection.getAll(activity, activity.getSettings().getEnabledLanguageIds(), true)) ); diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/LanguagesScreen.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/LanguagesScreen.java index 0a6049a1..b37b7ef9 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/LanguagesScreen.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/LanguagesScreen.java @@ -36,11 +36,7 @@ public class LanguagesScreen extends BaseScreenFragment { @Override protected void onCreate() { - ItemSelectLanguage multiSelect = new ItemSelectLanguage( - activity, - findPreference(ItemSelectLanguage.NAME) - ); - multiSelect.populate().enableValidation(); + new ItemSelectLanguage(activity, findPreference(ItemSelectLanguage.NAME)).populate(); new ItemDictionaryNotifications(findPreference(ItemDictionaryNotifications.NAME), activity) .populate() @@ -111,6 +107,7 @@ public class LanguagesScreen extends BaseScreenFragment { private void refreshItems() { + new ItemSelectLanguage(activity, findPreference(ItemSelectLanguage.NAME)).populate(); loadItem.refreshStatus(); exportDictionaryItem.refreshStatus(); exportCustomWordsItem.refreshStatus(); diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsInput.java b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsInput.java index a1030866..34e0ba24 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsInput.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsInput.java @@ -39,9 +39,11 @@ class SettingsInput extends SettingsHotkeys { public Set getEnabledLanguagesIdsAsStrings() { - return prefs.getStringSet("pref_languages", new HashSet<>(Collections.singletonList( + Set defaultLanguages = new HashSet<>(Collections.singletonList( String.valueOf(LanguageCollection.getDefault(context).getId()) - ))); + )); + + return new HashSet<>(prefs.getStringSet("pref_languages", defaultLanguages)); } diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java index 08876512..e3609f84 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java @@ -8,7 +8,6 @@ public class SettingsStore extends SettingsUI { /************* internal settings *************/ public final static int CLIPBOARD_PREVIEW_LENGTH = 20; - public final static int DELETE_WORDS_SEARCH_DELAY = 500; // ms public final static int CUSTOM_WORDS_IMPORT_MAX_LINES = 250; public final static int CUSTOM_WORDS_MAX = 1000; public final static int DICTIONARY_AUTO_LOAD_COOLDOWN_TIME = 1200000; // 20 minutes in ms @@ -28,6 +27,7 @@ public class SettingsStore extends SettingsUI { public final static int SUGGESTIONS_MIN = 8; public final static int SUGGESTIONS_SELECT_ANIMATION_DURATION = 66; public final static int SUGGESTIONS_TRANSLATE_ANIMATION_DURATION = 0; + public final static int TEXT_INPUT_DEBOUNCE_TIME = 500; // ms public final static int WORD_FREQUENCY_MAX = 25500; public final static int WORD_FREQUENCY_NORMALIZATION_DIVIDER = 100; // normalized frequency = WORD_FREQUENCY_MAX / WORD_FREQUENCY_NORMALIZATION_DIVIDER public final static int WORD_NORMALIZATION_DELAY = 15000; // ms diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index d448d597..04b7ce5b 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -64,8 +64,8 @@ Изтрий Намери и изтрий на неправилно написани или ненужни думи. Търси думи - Намерени думи - Няма резултати. + Намерени думи + Няма резултати. Потвърдете изтриването Наистина ли искате да изтриете „%1$s“? „%1$s“ беше изтрита. @@ -165,4 +165,8 @@ Импортиране на думи от по-рано експортирано CSV. Импортиране на CSV (%1$s)… Импортиране на CSV… + (зареден) + Избор на езици + Търси езици + думи diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 896d4163..7373be78 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -102,8 +102,8 @@ Löschen Finde und lösche falsch geschriebene oder überflüssige Wörter. Nach Wörtern suchen - Suchergebnisse - Keine Ergebnisse. + Suchergebnisse + Keine Ergebnisse. Löschung bestätigen Sind Sie sicher, dass Sie \"%1$s\" löschen möchten? \"%1$s\" wurde gelöscht. @@ -154,4 +154,8 @@ Wörter aus einer zuvor exportierten CSV-Datei importieren. CSV importieren (%1$s)… CSV importieren… + (geladen) + Sprachen aktivieren + Nach Sprachen suchen + Wörter diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 2cb35729..b897f917 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -115,8 +115,8 @@ Eliminar Buscar y eliminar palabras mal escritas o innecesarias. Buscar palabras - Palabras encontradas - Sin resultados. + Palabras encontradas + Sin resultados. Confirma la eliminación ¿Estás seguro de que quieres eliminar \"%1$s\"? \"%1$s\" fue eliminada. @@ -163,4 +163,8 @@ Importar palabras de un CSV previamente exportado. Importando CSV (%1$s)… Importando CSV… + (cargado) + Habilitar idiomas + Buscar idiomas + palabras diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 17d80d94..640387e5 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -117,8 +117,8 @@ Supprimer Trouver et supprimer des mots mal orthographiés ou inutiles. Rechercher des mots - Mots trouvés - Aucun résultat. + Mots trouvés + Aucun résultat. Confirmer la suppression Êtes-vous sûr de vouloir supprimer « %1$s » ? \"%1$s\" a été supprimé. @@ -161,4 +161,8 @@ Importer des mots à partir d\'un fichier CSV précédemment exporté. Importation de CSV (%1$s)… Importation de CSV… + (chargée) + Activer les langues + Rechercher des langues + mots diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index df6a68fd..9982a66a 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -102,8 +102,8 @@ Elimina Trova ed elimina parole errate o non necessarie. Ricerca di parole - Parole trovate - Nessun risultato. + Parole trovate + Nessun risultato. Conferma l\'eliminazione Sei sicuro di voler eliminare \"%1$s\"? \"%1$s\" è stata eliminata. @@ -153,5 +153,9 @@ Importare parole da un CSV precedentemente esportato. Importazione CSV (%1$s)… Importazione CSV… + (caricata) + Abilita lingue + Cerca lingue + parole diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 76a6c665..ce0e58ac 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -115,8 +115,8 @@ מחיקה מצא ומחק מילים שכתובות בטעות או שאינן נדרשות. חיפוש מילים - תוצאות חיפוש - אין תוצאות. + תוצאות חיפוש + אין תוצאות. אישור מחיקה האם אתה בטוח שברצונך להסיר את \"%1$s\"? \"%1$s\" נמחקה. @@ -166,4 +166,8 @@ ייבוא מילים מקובץ CSV שיוצא קודם לכן. מייבא CSV (%1$s)… מייבא CSV… + (נטען) + הפעל שפות + חיפוש שפות + מילים diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 0e77194b..aa97eec1 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -134,8 +134,8 @@ Ištrinti Raskite ir ištrinkite neteisingai parašytus arba nereikalingus žodžius. Ieškoti žodžių - Paieškos rezultatai - Jokių rezultatų. + Paieškos rezultatai + Jokių rezultatų. Patvirtinkite ištrynimą Ar tikrai norite ištrinti „%1$s“? „%1$s“ buvo ištrintas. @@ -172,4 +172,8 @@ Importuoti žodžius iš anksčiau eksportuoto CSV. Importuojamas CSV (%1$s)… Importuojamas CSV… + (įkelta) + Įjungti kalbas + Ieškoti kalbų + žodžių diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 70eefe76..bea41219 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -100,8 +100,8 @@ Verwijderen Zoek en verwijder verkeerd gespelde of onnodige woorden. Zoeken naar woorden - Zoekresultaten - Geen resultaten. + Zoekresultaten + Geen resultaten. Bevestig verwijdering Weet u zeker dat u \"%1$s\" wilt verwijderen? \"%1$s\" is verwijderd. @@ -152,4 +152,8 @@ Woorden importeren uit een eerder geëxporteerde CSV. CSV importeren (%1$s)… CSV importeren… + (geladen) + Talen inschakelen + Zoeken naar talen + woorden diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index b1f00e39..7e568256 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -115,8 +115,8 @@ Excluir Encontrar e excluir palavras escritas incorretamente ou desnecessárias. Buscar palavras - Palavras encontradas - Sem resultados. + Palavras encontradas + Sem resultados. Confirme a exclusão Tem certeza de que deseja excluir \"%1$s\"? \"%1$s\" foi excluída. @@ -166,4 +166,8 @@ Importar palavras de um CSV previamente exportado. Importando CSV (%1$s)… Importando CSV… + (carregado) + Habilitar idiomas + Buscar por idiomas + palavras diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d2775252..1cc8852d 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -116,8 +116,8 @@ Удалить Найти и удалить ошибочно написанные или ненужные слова. Поиск слов - Найденные слова - Нет результатов. + Найденные слова + Нет результатов. Подтвердите удаление Уверены, что хотите удалить «%1$s»? \"%1$s\" было удалено. @@ -163,4 +163,8 @@ Импортировать слова из ранее экспортированного CSV. Импортирование CSV (%1$s)… Импортирование CSV… + (загружен) + Включить языки + Поиск языков + слов diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index bfe887d9..c1c2784f 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -100,8 +100,8 @@ Sil Yanlış yazılan ya da gereksiz kelimeleri bulun ve silin. Aramak istediğiniz kelimeyi yazın… - Ara - Eşleşme bulunamadı. + Ara + Eşleşme bulunamadı. Silmeyi Onayla \"%1$s\" kelimesini silmeyi onaylıyor musunuz? \"%1$s\" kelimesi başarıyla silindi. @@ -166,4 +166,8 @@ Daha önce dışa aktarılan bir CSV\'den kelimeleri içe aktar. CSV İçe aktarılıyor (%1$s)… CSV İçe aktarılıyor… + (yüklendi) + Dilleri etkinleştir + Diller için arama + kelime diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index c94624c6..4b761f4e 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -99,8 +99,8 @@ Видалити Знайти та видалити неправильно написані або зайві слова. Пошук слів - Знайдені слова - Немає результатів. + Знайдені слова + Немає результатів. Підтвердіть видалення Ви впевнені, що хочете видалити \"%1$s\"? \"%1$s\" було видалено. @@ -174,4 +174,8 @@ Імпортувати слова з раніше експортованого CSV. Імпорт CSV (%1$s)… Імпорт CSV… + (завантажено) + Увімкнути мови + Пошук мов + слів diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2ed9f21b..e12d00ee 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8,6 +8,8 @@ Error Loading… No Language + Search Results + No results. Unexpected error occurred. Failed loading all language definitions. @@ -125,8 +127,6 @@ Delete Find and delete misspelled or unneeded words. Search for Words - Search Results - No results. Confirm Deletion Are you sure you want to delete \"%1$s\"? \"%1$s\" was deleted. @@ -155,6 +155,12 @@ Restore Default Keys Default key settings restored. + (loaded) + Enable Languages + Search for Languages + words + + Status Select Default Keyboard %1$s is enabled diff --git a/app/src/main/res/xml/prefs_screen_delete_words.xml b/app/src/main/res/xml/prefs_screen_delete_words.xml index 573d8dd4..938efd5e 100644 --- a/app/src/main/res/xml/prefs_screen_delete_words.xml +++ b/app/src/main/res/xml/prefs_screen_delete_words.xml @@ -7,5 +7,5 @@ + android:title="@string/search_results" /> diff --git a/app/src/main/res/xml/prefs_screen_language_selection.xml b/app/src/main/res/xml/prefs_screen_language_selection.xml new file mode 100644 index 00000000..2eea3084 --- /dev/null +++ b/app/src/main/res/xml/prefs_screen_language_selection.xml @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/app/src/main/res/xml/prefs_screen_languages.xml b/app/src/main/res/xml/prefs_screen_languages.xml index 9c70af92..9a037979 100644 --- a/app/src/main/res/xml/prefs_screen_languages.xml +++ b/app/src/main/res/xml/prefs_screen_languages.xml @@ -1,7 +1,8 @@ -