make secondary language selectable by user

This commit is contained in:
Helium 2022-03-19 15:03:07 +01:00
parent 3fe1e2f30b
commit 26efc80981
6 changed files with 129 additions and 9 deletions

View file

@ -31,8 +31,10 @@ import org.dslul.openboard.inputmethod.latin.common.Constants;
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
import org.dslul.openboard.inputmethod.latin.permissions.PermissionsUtil;
import org.dslul.openboard.inputmethod.latin.personalization.UserHistoryDictionary;
import org.dslul.openboard.inputmethod.latin.settings.Settings;
import org.dslul.openboard.inputmethod.latin.settings.SettingsValuesForSuggestion;
import org.dslul.openboard.inputmethod.latin.utils.ExecutorUtils;
import org.dslul.openboard.inputmethod.latin.utils.ScriptUtils;
import org.dslul.openboard.inputmethod.latin.utils.SuggestionResults;
import java.io.File;
@ -70,7 +72,6 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
private DictionaryGroup mDictionaryGroup = new DictionaryGroup();
private DictionaryGroup mSecondaryDictionaryGroup = new DictionaryGroup();
private Locale mSecondaryLocale = Locale.GERMAN;
private volatile CountDownLatch mLatchForWaitingLoadingMainDictionaries = new CountDownLatch(0);
// To synchronize assigning mDictionaryGroup to ensure closing dictionaries.
private final Object mLock = new Object();
@ -152,17 +153,17 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
// typing in. For now, this is simply the number of times a word from this language
// has been committed in a row, with an exception when typing a single word not contained
// in this language.
private int mConfidence = 0;
private int mConfidence = 1;
// allow to go above max confidence for better determination of current preferred language
// but when decreasing confidence or getting weight factor, limit to maximum
public void increaseConfidence() {
mConfidence += 1;
mConfidence += 1;
}
public void decreaseConfidence() {
if (mConfidence > MAX_CONFIDENCE)
mConfidence = MAX_CONFIDENCE - 1;
mConfidence = MAX_CONFIDENCE;
else if (mConfidence > MIN_CONFIDENCE)
mConfidence -= 1;
}
@ -392,14 +393,9 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
dictTypesToCleanupForLocale.remove(subDictType);
}
subDicts.put(subDictType, subDict);
// what is dictNamePrefix? apparently empty string...
secondarySubDicts.put(subDictType, getSubDict(subDictType, context, mSecondaryLocale, null, dictNamePrefix, account));
}
DictionaryGroup newDictionaryGroup =
new DictionaryGroup(newLocale, mainDict, account, subDicts);
// TODO: get secondary locale from prefs or whatever (context!)
mSecondaryDictionaryGroup = new DictionaryGroup(mSecondaryLocale, null, account, secondarySubDicts);
mSecondaryDictionaryGroup.setMainDict(DictionaryFactory.createMainDictionaryFromManager(context, mSecondaryLocale));
// Replace Dictionaries.
final DictionaryGroup oldDictionaryGroup;
@ -414,6 +410,21 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
listener.onUpdateMainDictionaryAvailability(hasAtLeastOneInitializedMainDictionary());
}
// create / load secondary dictionary
final Locale secondaryLocale = Settings.getInstance().getCurrent().mSecondaryLocale;
if (secondaryLocale != null && mainDict != null &&
ScriptUtils.getScriptFromSpellCheckerLocale(secondaryLocale) == ScriptUtils.getScriptFromSpellCheckerLocale(mainDict.mLocale)) {
for (final String subDictType : subDictTypesToUse) {
final ExpandableBinaryDictionary subDict =
getSubDict(subDictType, context, newLocale, null, dictNamePrefix, account);
secondarySubDicts.put(subDictType, subDict);
}
mSecondaryDictionaryGroup = new DictionaryGroup(secondaryLocale, null, account, secondarySubDicts);
mSecondaryDictionaryGroup.setMainDict(DictionaryFactory.createMainDictionaryFromManager(context, secondaryLocale));
} else {
mSecondaryDictionaryGroup = null;
}
// Clean up old dictionaries.
for (final Locale localeToCleanUp : existingDictionariesToCleanup.keySet()) {
final ArrayList<String> dictTypesToCleanUp =

View file

@ -16,14 +16,35 @@
package org.dslul.openboard.inputmethod.latin.settings;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.LocaleList;
import android.preference.Preference;
import android.util.ArraySet;
import android.util.Log;
import androidx.core.os.LocaleListCompat;
import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants;
import org.dslul.openboard.inputmethod.latin.AudioAndHapticFeedbackManager;
import org.dslul.openboard.inputmethod.latin.R;
import org.dslul.openboard.inputmethod.latin.SystemBroadcastReceiver;
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils;
import org.dslul.openboard.inputmethod.latin.utils.DialogUtils;
import org.dslul.openboard.inputmethod.latin.utils.DictionaryInfoUtils;
import org.dslul.openboard.inputmethod.latin.utils.ScriptUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
/**
* "Advanced" settings sub screen.
@ -57,6 +78,16 @@ public final class AdvancedSettingsFragment extends SubScreenFragment {
}
setupKeyLongpressTimeoutSettings();
final Preference setSecondaryLocale = findPreference("pref_secondary_locale");
if (setSecondaryLocale != null)
setSecondaryLocale.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showSecondaryLocaleDialog();
return true;
}
});
}
@ -105,4 +136,57 @@ public final class AdvancedSettingsFragment extends SubScreenFragment {
SystemBroadcastReceiver.toggleAppIcon(getActivity());
}
}
private void showSecondaryLocaleDialog() {
// only latin for now
final List<String> locales = new ArrayList<String>(getAvailableDictionaryLocalesForScript(ScriptUtils.SCRIPT_LATIN));
final AlertDialog.Builder builder = new AlertDialog.Builder(
DialogUtils.getPlatformDialogThemeContext(getActivity()))
.setTitle(R.string.select_language)
.setPositiveButton(android.R.string.ok, null);
if (locales.isEmpty()) {
builder.setMessage(R.string.no_secondary_locales)
.show();
return;
}
locales.add(getResources().getString(R.string.secondary_locale_none));
final CharSequence[] titles = locales.toArray(new CharSequence[0]);
for (int i = 0; i < titles.length -1 ; i++) {
titles[i] = LocaleUtils.constructLocaleFromString(titles[i].toString()).getDisplayLanguage();
}
Locale currentSecondaryLocale = Settings.getInstance().getCurrent().mSecondaryLocale;
int checkedItem;
if (currentSecondaryLocale == null)
checkedItem = locales.size() - 1;
else
checkedItem = locales.indexOf(currentSecondaryLocale.toString());
builder.setSingleChoiceItems(titles, checkedItem, (dialogInterface, i) -> {
String locale = locales.get(i);
if (locale.equals(getResources().getString(R.string.secondary_locale_none)))
locale = "";
getSharedPreferences().edit().putString(Settings.PREF_SECONDARY_LOCALE, locale).apply();
final Intent newDictBroadcast = new Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION);
getActivity().sendBroadcast(newDictBroadcast);
});
builder.show();
}
private Set<String> getAvailableDictionaryLocalesForScript(int script) {
final Set<String> locales = new HashSet<>();
// TODO: get from assets
// need merged "compress" PR
// filter by script!
final File[] directoryList = DictionaryInfoUtils.getCachedDirectoryList(getActivity());
for (File directory : directoryList) {
if (!directory.isDirectory()) continue;
final String dirLocale =
DictionaryInfoUtils.getWordListIdFromFileName(directory.getName());
final Locale locale = LocaleUtils.constructLocaleFromString(dirLocale);
if (ScriptUtils.getScriptFromSpellCheckerLocale(locale) != script) continue;
locales.add(locale.toString());
}
return locales;
}
}

View file

@ -29,6 +29,7 @@ import android.view.Gravity;
import org.dslul.openboard.inputmethod.latin.AudioAndHapticFeedbackManager;
import org.dslul.openboard.inputmethod.latin.InputAttributes;
import org.dslul.openboard.inputmethod.latin.R;
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils;
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
import org.dslul.openboard.inputmethod.latin.utils.AdditionalSubtypeUtils;
import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils;
@ -126,6 +127,8 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_ENABLE_CLIPBOARD_HISTORY = "pref_enable_clipboard_history";
public static final String PREF_CLIPBOARD_HISTORY_RETENTION_TIME = "pref_clipboard_history_retention_time";
public static final String PREF_SECONDARY_LOCALE = "pref_secondary_locale";
// This preference key is deprecated. Use {@link #PREF_SHOW_LANGUAGE_SWITCH_KEY} instead.
// This is being used only for the backward compatibility.
private static final String PREF_SUPPRESS_LANGUAGE_SWITCH_KEY =
@ -509,6 +512,13 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
return prefs.getInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_PAGE_ID, defValue);
}
public static Locale readSecondaryLocale(final SharedPreferences prefs) {
final String localeString = prefs.getString(PREF_SECONDARY_LOCALE, "");
if (localeString.isEmpty())
return null;
return LocaleUtils.constructLocaleFromString(localeString);
}
private void upgradeAutocorrectionSettings(final SharedPreferences prefs, final Resources res) {
final String thresholdSetting =
prefs.getString(PREF_AUTO_CORRECTION_THRESHOLD_OBSOLETE, null);

View file

@ -84,6 +84,7 @@ public class SettingsValues {
public final long mClipboardHistoryRetentionTime;
public final boolean mOneHandedModeEnabled;
public final int mOneHandedModeGravity;
public final Locale mSecondaryLocale;
// Use bigrams to predict the next word when there is no input for it yet
public final boolean mBigramPredictionEnabled;
public final boolean mGestureInputEnabled;
@ -241,6 +242,7 @@ public class SettingsValues {
mClipboardHistoryRetentionTime = Settings.readClipboardHistoryRetentionTime(prefs, res);
mOneHandedModeEnabled = Settings.readOneHandedModeEnabled(prefs);
mOneHandedModeGravity = Settings.readOneHandedModeGravity(prefs);
mSecondaryLocale = Settings.readSecondaryLocale(prefs);
}
public boolean isMetricsLoggingEnabled() {

View file

@ -184,6 +184,14 @@
<string name="delete_swipe_summary">Perform a swipe from the delete key to select and remove bigger portions of text at once</string>
<!-- Preferences item for enabling trackpad space key -->
<string name="space_trackpad">Space bar trackpad</string>
<!-- Preferences item for choosing secondary language -->
<string name="secondary_locale">Multilingual typing</string>
<!-- Description for "secondary_locale" option. -->
<string name="secondary_locale_summary">Select a secondary dictionary to use alongside main language</string>
<!-- Text when no secondary locale chosen -->
<string name="secondary_locale_none">None</string>
<!-- Message shown when no secondary locales available -->
<string name="no_secondary_locales">No secondary locales available</string>
<!-- Description for "space_trackpad" option. -->
<string name="space_trackpad_summary">Swipe on the spacebar to move the cursor</string>
<!-- Preferences item for disabling word learning -->

View file

@ -76,6 +76,11 @@
android:summary="@string/delete_swipe_summary"
android:defaultValue="true" />
<Preference
android:key="pref_secondary_locale"
android:title="@string/secondary_locale"
android:summary="@string/secondary_locale_summary" />
</PreferenceCategory>
</PreferenceScreen>