mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-17 15:32:48 +00:00
add backup / restore option
and convert AdvancedSettingsFragment to kotlin fixes #200
This commit is contained in:
parent
62dd2d954f
commit
b8f4f589e8
8 changed files with 283 additions and 173 deletions
|
@ -405,7 +405,7 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
|
||||||
final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
|
final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
|
||||||
for (final String subDictType : subDictTypesToUse) {
|
for (final String subDictType : subDictTypesToUse) {
|
||||||
final ExpandableBinaryDictionary subDict;
|
final ExpandableBinaryDictionary subDict;
|
||||||
if (noExistingDictsForThisLocale
|
if (noExistingDictsForThisLocale || forceReloadMainDictionary
|
||||||
|| !oldDictionaryGroupForLocale.hasDict(subDictType, account)) {
|
|| !oldDictionaryGroupForLocale.hasDict(subDictType, account)) {
|
||||||
// Create a new dictionary.
|
// Create a new dictionary.
|
||||||
subDict = getSubDict(subDictType, context, locale, null /* dictFile */, dictNamePrefix, account);
|
subDict = getSubDict(subDictType, context, locale, null /* dictFile */, dictNamePrefix, account);
|
||||||
|
|
|
@ -1,158 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 The Android Open Source Project
|
|
||||||
* modified
|
|
||||||
* SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.dslul.openboard.inputmethod.latin.settings;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Process;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
|
|
||||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet;
|
|
||||||
import org.dslul.openboard.inputmethod.latin.AudioAndHapticFeedbackManager;
|
|
||||||
import org.dslul.openboard.inputmethod.latin.BuildConfig;
|
|
||||||
import org.dslul.openboard.inputmethod.latin.R;
|
|
||||||
import org.dslul.openboard.inputmethod.latin.SystemBroadcastReceiver;
|
|
||||||
import org.dslul.openboard.inputmethod.latin.common.FileUtils;
|
|
||||||
import org.dslul.openboard.inputmethod.latin.define.JniLibName;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* "Advanced" settings sub screen.
|
|
||||||
*
|
|
||||||
* This settings sub screen handles the following advanced preferences.
|
|
||||||
* - Key popup dismiss delay
|
|
||||||
* - Keypress vibration duration
|
|
||||||
* - Keypress sound volume
|
|
||||||
* - Show app icon
|
|
||||||
* - Improve keyboard
|
|
||||||
* - Debug settings
|
|
||||||
*/
|
|
||||||
public final class AdvancedSettingsFragment extends SubScreenFragment {
|
|
||||||
private final int REQUEST_CODE_GESTURE_LIBRARY = 570289;
|
|
||||||
File libfile = null;
|
|
||||||
@Override
|
|
||||||
public void onCreate(final Bundle icicle) {
|
|
||||||
super.onCreate(icicle);
|
|
||||||
addPreferencesFromResource(R.xml.prefs_screen_advanced);
|
|
||||||
|
|
||||||
final Context context = requireContext();
|
|
||||||
|
|
||||||
// When we are called from the Settings application but we are not already running, some
|
|
||||||
// singleton and utility classes may not have been initialized. We have to call
|
|
||||||
// initialization method of these classes here. See {@link LatinIME#onCreate()}.
|
|
||||||
AudioAndHapticFeedbackManager.init(context);
|
|
||||||
|
|
||||||
if (!BuildConfig.DEBUG) {
|
|
||||||
removePreference(Settings.SCREEN_DEBUG);
|
|
||||||
}
|
|
||||||
|
|
||||||
setupKeyLongpressTimeoutSettings();
|
|
||||||
final Preference loadGestureLibrary = findPreference("load_gesture_library");
|
|
||||||
if (loadGestureLibrary != null) {
|
|
||||||
loadGestureLibrary.setOnPreferenceClickListener(preference -> {
|
|
||||||
// get architecture for telling user which file to use
|
|
||||||
String abi;
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
abi = Build.SUPPORTED_ABIS[0];
|
|
||||||
} else {
|
|
||||||
abi = Build.CPU_ABI;
|
|
||||||
}
|
|
||||||
// show delete / add dialog
|
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
|
||||||
.setTitle(R.string.load_gesture_library)
|
|
||||||
.setMessage(context.getString(R.string.load_gesture_library_message, abi))
|
|
||||||
.setPositiveButton(R.string.load_gesture_library_button_load, (dialogInterface, i) -> {
|
|
||||||
final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT)
|
|
||||||
.addCategory(Intent.CATEGORY_OPENABLE)
|
|
||||||
.setType("application/octet-stream");
|
|
||||||
startActivityForResult(intent, REQUEST_CODE_GESTURE_LIBRARY);
|
|
||||||
})
|
|
||||||
.setNegativeButton(android.R.string.cancel, null);
|
|
||||||
libfile = new File(context.getFilesDir().getAbsolutePath() + File.separator + JniLibName.JNI_LIB_IMPORT_FILE_NAME);
|
|
||||||
if (libfile.exists())
|
|
||||||
builder.setNeutralButton(R.string.load_gesture_library_button_delete, (dialogInterface, i) -> {
|
|
||||||
libfile.delete();
|
|
||||||
Runtime.getRuntime().exit(0);
|
|
||||||
});
|
|
||||||
builder.show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
|
|
||||||
if (requestCode != REQUEST_CODE_GESTURE_LIBRARY || resultCode != Activity.RESULT_OK || resultData == null) return;
|
|
||||||
if (resultData.getData() != null && libfile != null) {
|
|
||||||
try {
|
|
||||||
final InputStream in = requireContext().getContentResolver().openInputStream(resultData.getData());
|
|
||||||
FileUtils.copyStreamToNewFile(in, libfile);
|
|
||||||
Runtime.getRuntime().exit(0); // exit will restart the app, so library will be loaded
|
|
||||||
} catch (IOException e) {
|
|
||||||
// should inform user, but probably the issues will only come when reading the library
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void setupKeyLongpressTimeoutSettings() {
|
|
||||||
final SharedPreferences prefs = getSharedPreferences();
|
|
||||||
final Resources res = getResources();
|
|
||||||
final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
|
|
||||||
Settings.PREF_KEY_LONGPRESS_TIMEOUT);
|
|
||||||
if (pref == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
|
|
||||||
@Override
|
|
||||||
public void writeValue(final int value, final String key) {
|
|
||||||
prefs.edit().putInt(key, value).apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeDefaultValue(final String key) {
|
|
||||||
prefs.edit().remove(key).apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readValue(final String key) {
|
|
||||||
return Settings.readKeyLongpressTimeout(prefs, res);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readDefaultValue(final String key) {
|
|
||||||
return Settings.readDefaultKeyLongpressTimeout(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getValueText(final int value) {
|
|
||||||
return res.getString(R.string.abbreviation_unit_milliseconds, Integer.toString(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void feedbackValue(final int value) {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
|
|
||||||
if (key.equals(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) {
|
|
||||||
SystemBroadcastReceiver.toggleAppIcon(requireContext());
|
|
||||||
} else if (key.equals(Settings.PREF_SHOW_ALL_MORE_KEYS)) {
|
|
||||||
KeyboardLayoutSet.onKeyboardThemeChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,238 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014 The Android Open Source Project
|
||||||
|
* modified
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
|
||||||
|
*/
|
||||||
|
package org.dslul.openboard.inputmethod.latin.settings
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants
|
||||||
|
import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet
|
||||||
|
import org.dslul.openboard.inputmethod.latin.AudioAndHapticFeedbackManager
|
||||||
|
import org.dslul.openboard.inputmethod.latin.BuildConfig
|
||||||
|
import org.dslul.openboard.inputmethod.latin.R
|
||||||
|
import org.dslul.openboard.inputmethod.latin.RichInputMethodManager
|
||||||
|
import org.dslul.openboard.inputmethod.latin.SystemBroadcastReceiver
|
||||||
|
import org.dslul.openboard.inputmethod.latin.common.FileUtils
|
||||||
|
import org.dslul.openboard.inputmethod.latin.define.JniLibName
|
||||||
|
import org.dslul.openboard.inputmethod.latin.settings.SeekBarDialogPreference.ValueProxy
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.zip.ZipEntry
|
||||||
|
import java.util.zip.ZipInputStream
|
||||||
|
import java.util.zip.ZipOutputStream
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Advanced" settings sub screen.
|
||||||
|
*
|
||||||
|
* This settings sub screen handles the following advanced preferences.
|
||||||
|
* - Key popup dismiss delay
|
||||||
|
* - Keypress vibration duration
|
||||||
|
* - Keypress sound volume
|
||||||
|
* - Show app icon
|
||||||
|
* - Improve keyboard
|
||||||
|
* - Debug settings
|
||||||
|
*/
|
||||||
|
class AdvancedSettingsFragment : SubScreenFragment() {
|
||||||
|
private var libfile: File? = null
|
||||||
|
private val backupFilePatterns by lazy { listOf(
|
||||||
|
"blacklists/.*\\.txt".toRegex(),
|
||||||
|
"dicts/.*/.*user\\.dict".toRegex(),
|
||||||
|
"userunigram.*/userunigram.*\\.(body|header)".toRegex(),
|
||||||
|
"UserHistoryDictionary.*/UserHistoryDictionary.*\\.(body|header)".toRegex(),
|
||||||
|
"spellcheck_userunigram.*/spellcheck_userunigram.*\\.(body|header)".toRegex(),
|
||||||
|
// todo: found "b.<locale>.dict" folder, where does it come from?
|
||||||
|
// possibly some obfuscation thing that occurred after upgrading to gradle 8?
|
||||||
|
) }
|
||||||
|
|
||||||
|
override fun onCreate(icicle: Bundle?) {
|
||||||
|
super.onCreate(icicle)
|
||||||
|
addPreferencesFromResource(R.xml.prefs_screen_advanced)
|
||||||
|
val context = requireContext()
|
||||||
|
|
||||||
|
// When we are called from the Settings application but we are not already running, some
|
||||||
|
// singleton and utility classes may not have been initialized. We have to call
|
||||||
|
// initialization method of these classes here. See {@link LatinIME#onCreate()}.
|
||||||
|
AudioAndHapticFeedbackManager.init(context)
|
||||||
|
if (!BuildConfig.DEBUG) {
|
||||||
|
removePreference(Settings.SCREEN_DEBUG)
|
||||||
|
}
|
||||||
|
setupKeyLongpressTimeoutSettings()
|
||||||
|
findPreference<Preference>("load_gesture_library")?.setOnPreferenceClickListener { onClickLoadLibrary() }
|
||||||
|
findPreference<Preference>("pref_backup_restore")?.setOnPreferenceClickListener { showBackupRestoreDialog() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onClickLoadLibrary(): Boolean {
|
||||||
|
// get architecture for telling user which file to use
|
||||||
|
val abi = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
Build.SUPPORTED_ABIS[0]
|
||||||
|
} else {
|
||||||
|
Build.CPU_ABI
|
||||||
|
}
|
||||||
|
// show delete / add dialog
|
||||||
|
val builder = AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle(R.string.load_gesture_library)
|
||||||
|
.setMessage(requireContext().getString(R.string.load_gesture_library_message, abi))
|
||||||
|
.setPositiveButton(R.string.load_gesture_library_button_load) { _, _ ->
|
||||||
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
|
||||||
|
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
.setType("application/octet-stream")
|
||||||
|
startActivityForResult(intent, REQUEST_CODE_GESTURE_LIBRARY)
|
||||||
|
}
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
libfile = File(requireContext().filesDir.absolutePath + File.separator + JniLibName.JNI_LIB_IMPORT_FILE_NAME)
|
||||||
|
if (libfile?.exists() == true) {
|
||||||
|
builder.setNeutralButton(R.string.load_gesture_library_button_delete) { _, _ ->
|
||||||
|
libfile?.delete()
|
||||||
|
Runtime.getRuntime().exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.show()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) {
|
||||||
|
val uri = result?.data
|
||||||
|
if (resultCode != Activity.RESULT_OK || uri == null) return
|
||||||
|
when (requestCode) {
|
||||||
|
REQUEST_CODE_GESTURE_LIBRARY -> copyLibrary(uri)
|
||||||
|
REQUEST_CODE_BACKUP -> backup(uri)
|
||||||
|
REQUEST_CODE_RESTORE -> restore(uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyLibrary(uri: Uri) {
|
||||||
|
if (libfile == null) return
|
||||||
|
try {
|
||||||
|
val inputStream = requireContext().contentResolver.openInputStream(uri)
|
||||||
|
FileUtils.copyStreamToNewFile(inputStream, libfile)
|
||||||
|
Runtime.getRuntime().exit(0) // exit will restart the app, so library will be loaded
|
||||||
|
} catch (e: IOException) {
|
||||||
|
// should inform user, but probably the issues will only come when reading the library
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showBackupRestoreDialog(): Boolean {
|
||||||
|
AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle(R.string.backup_restore_title)
|
||||||
|
.setMessage(R.string.backup_restore_message)
|
||||||
|
.setNegativeButton(R.string.button_backup) { _, _ ->
|
||||||
|
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
||||||
|
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
.putExtra(
|
||||||
|
Intent.EXTRA_TITLE,
|
||||||
|
requireContext().getString(R.string.english_ime_name)
|
||||||
|
.replace(" ", "_") + "_backup.zip"
|
||||||
|
)
|
||||||
|
.setType("application/zip")
|
||||||
|
startActivityForResult(intent, REQUEST_CODE_BACKUP)
|
||||||
|
}
|
||||||
|
.setPositiveButton(android.R.string.cancel, null)
|
||||||
|
.setNeutralButton(R.string.button_restore) { _, _ ->
|
||||||
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
|
||||||
|
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
.setType("application/zip")
|
||||||
|
startActivityForResult(intent, REQUEST_CODE_RESTORE)
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun backup(uri: Uri) {
|
||||||
|
// zip all files matching the backup patterns
|
||||||
|
// essentially this is the typed words information, and user-added dictionaries
|
||||||
|
val filesDir = requireContext().filesDir ?: return
|
||||||
|
val filesPath = filesDir.path + File.separator
|
||||||
|
val files = mutableListOf<File>()
|
||||||
|
filesDir.walk().forEach { file ->
|
||||||
|
val path = file.path.replace(filesPath, "")
|
||||||
|
if (backupFilePatterns.any { path.matches(it) })
|
||||||
|
files.add(file)
|
||||||
|
}
|
||||||
|
if (files.isEmpty()) {
|
||||||
|
infoDialog(requireContext(), R.string.backup_error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
activity?.contentResolver?.openOutputStream(uri)?.use { os ->
|
||||||
|
// write files to zip
|
||||||
|
val zipStream = ZipOutputStream(os)
|
||||||
|
files.forEach {
|
||||||
|
val fileStream = FileInputStream(it).buffered()
|
||||||
|
zipStream.putNextEntry(ZipEntry(it.path.replace(filesPath, "")))
|
||||||
|
fileStream.copyTo(zipStream, 1024)
|
||||||
|
fileStream.close()
|
||||||
|
zipStream.closeEntry()
|
||||||
|
}
|
||||||
|
zipStream.close()
|
||||||
|
}
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
// inform about every error
|
||||||
|
infoDialog(requireContext(), R.string.backup_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun restore(uri: Uri) {
|
||||||
|
try {
|
||||||
|
activity?.contentResolver?.openInputStream(uri)?.use { inputStream ->
|
||||||
|
ZipInputStream(inputStream).use { zip ->
|
||||||
|
var entry: ZipEntry? = zip.nextEntry
|
||||||
|
val filesDir = requireContext().filesDir?.path ?: return
|
||||||
|
while (entry != null) {
|
||||||
|
if (backupFilePatterns.any { entry!!.name.matches(it) }) {
|
||||||
|
val file = File(filesDir, entry.name)
|
||||||
|
FileUtils.copyStreamToNewFile(zip, file)
|
||||||
|
}
|
||||||
|
zip.closeEntry()
|
||||||
|
entry = zip.nextEntry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val newDictBroadcast = Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION)
|
||||||
|
activity?.sendBroadcast(newDictBroadcast)
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
// inform about every error
|
||||||
|
infoDialog(requireContext(), requireContext().getString(R.string.restore_error, t.message))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupKeyLongpressTimeoutSettings() {
|
||||||
|
val prefs = sharedPreferences
|
||||||
|
findPreference<SeekBarDialogPreference>(Settings.PREF_KEY_LONGPRESS_TIMEOUT)?.setInterface(object : ValueProxy {
|
||||||
|
override fun writeValue(value: Int, key: String) = prefs.edit().putInt(key, value).apply()
|
||||||
|
|
||||||
|
override fun writeDefaultValue(key: String) = prefs.edit().remove(key).apply()
|
||||||
|
|
||||||
|
override fun readValue(key: String) = Settings.readKeyLongpressTimeout(prefs, resources)
|
||||||
|
|
||||||
|
override fun readDefaultValue(key: String) = Settings.readDefaultKeyLongpressTimeout(resources)
|
||||||
|
|
||||||
|
override fun getValueText(value: Int) =
|
||||||
|
resources.getString(R.string.abbreviation_unit_milliseconds, value.toString())
|
||||||
|
|
||||||
|
override fun feedbackValue(value: Int) {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSharedPreferenceChanged(prefs: SharedPreferences, key: String?) {
|
||||||
|
if (Settings.PREF_SHOW_SETUP_WIZARD_ICON == key) {
|
||||||
|
SystemBroadcastReceiver.toggleAppIcon(requireContext())
|
||||||
|
} else if (Settings.PREF_SHOW_ALL_MORE_KEYS == key) {
|
||||||
|
KeyboardLayoutSet.onKeyboardThemeChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val REQUEST_CODE_GESTURE_LIBRARY = 570289
|
||||||
|
private const val REQUEST_CODE_BACKUP = 98665973
|
||||||
|
private const val REQUEST_CODE_RESTORE = 98665974
|
|
@ -280,14 +280,6 @@ class LanguageSettingsDialog(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun confirmDialog(context: Context, message: String, confirmButton: String, onConfirmed: (() -> Unit)) {
|
|
||||||
AlertDialog.Builder(context)
|
|
||||||
.setMessage(message)
|
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
|
||||||
.setPositiveButton(confirmButton) { _, _ -> onConfirmed() }
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return list of user dictionary files and whether an internal dictionary exists */
|
/** @return list of user dictionary files and whether an internal dictionary exists */
|
||||||
fun getUserAndInternalDictionaries(context: Context, locale: String): Pair<List<File>, Boolean> {
|
fun getUserAndInternalDictionaries(context: Context, locale: String): Pair<List<File>, Boolean> {
|
||||||
val localeString = locale.lowercase() // internal files and folders always use lowercase
|
val localeString = locale.lowercase() // internal files and folders always use lowercase
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.dslul.openboard.inputmethod.latin.settings
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
|
||||||
|
// maybe rather put to DialogUtils (and convert that to kotlin)
|
||||||
|
|
||||||
|
fun confirmDialog(context: Context, message: String, confirmButton: String, onConfirmed: (() -> Unit)) {
|
||||||
|
AlertDialog.Builder(context)
|
||||||
|
.setMessage(message)
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.setPositiveButton(confirmButton) { _, _ -> onConfirmed() }
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun infoDialog(context: Context, messageId: Int) {
|
||||||
|
AlertDialog.Builder(context)
|
||||||
|
.setMessage(messageId)
|
||||||
|
.setNegativeButton(android.R.string.ok, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
fun infoDialog(context: Context, message: String) {
|
||||||
|
AlertDialog.Builder(context)
|
||||||
|
.setMessage(message)
|
||||||
|
.setNegativeButton(android.R.string.ok, null)
|
||||||
|
.show()
|
||||||
|
}
|
|
@ -5,7 +5,6 @@ package org.dslul.openboard.inputmethod.latin.utils
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants
|
import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants
|
||||||
import org.dslul.openboard.inputmethod.latin.R
|
import org.dslul.openboard.inputmethod.latin.R
|
||||||
|
@ -15,7 +14,6 @@ import org.dslul.openboard.inputmethod.latin.makedict.DictionaryHeader
|
||||||
import org.dslul.openboard.inputmethod.latin.settings.*
|
import org.dslul.openboard.inputmethod.latin.settings.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.text.DateFormat
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class NewDictionaryAdder(private val context: Context, private val onAdded: ((Boolean, File) -> Unit)?) {
|
class NewDictionaryAdder(private val context: Context, private val onAdded: ((Boolean, File) -> Unit)?) {
|
||||||
|
@ -146,10 +144,7 @@ class NewDictionaryAdder(private val context: Context, private val onAdded: ((Bo
|
||||||
// Toast.makeText(context, messageId, Toast.LENGTH_LONG).show()
|
// Toast.makeText(context, messageId, Toast.LENGTH_LONG).show()
|
||||||
// show a dialog because toasts are not showing up on some Android versions
|
// show a dialog because toasts are not showing up on some Android versions
|
||||||
// possibly Android 13 because of notification permission
|
// possibly Android 13 because of notification permission
|
||||||
AlertDialog.Builder(context)
|
infoDialog(context, messageId)
|
||||||
.setMessage(messageId)
|
|
||||||
.setNegativeButton(R.string.dialog_close, null)
|
|
||||||
.show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,18 @@
|
||||||
<string name="space_language_slide">Space bar language slide</string>
|
<string name="space_language_slide">Space bar language slide</string>
|
||||||
<!-- Description for "space_language_slide" option. -->
|
<!-- Description for "space_language_slide" option. -->
|
||||||
<string name="space_language_slide_summary">Swipe upwards on the spacebar to change the language</string>
|
<string name="space_language_slide_summary">Swipe upwards on the spacebar to change the language</string>
|
||||||
|
<!-- Preferences item and dialog title for backup and restore -->
|
||||||
|
<string name="backup_restore_title">Backup and restore</string>
|
||||||
|
<!-- Message for backup and restore dialog -->
|
||||||
|
<string name="backup_restore_message">Save or load from file. Warning: restore will overwrite existing data</string>
|
||||||
|
<!-- Error message for backup -->
|
||||||
|
<string name="backup_error">Backup error</string>
|
||||||
|
<!-- Error message for restore, %s is replaced by the error message -->
|
||||||
|
<string name="restore_error">Error restoring the backup: %s</string>
|
||||||
|
<!-- backup button -->
|
||||||
|
<string name="button_backup">Backup</string>
|
||||||
|
<!-- restore button -->
|
||||||
|
<string name="button_restore">Restore</string>
|
||||||
<!-- Preferences item for choosing secondary language -->
|
<!-- Preferences item for choosing secondary language -->
|
||||||
<string name="secondary_locale">Multilingual typing</string>
|
<string name="secondary_locale">Multilingual typing</string>
|
||||||
<!-- Preferences item for loading an external gesture typing library -->
|
<!-- Preferences item for loading an external gesture typing library -->
|
||||||
|
|
|
@ -56,6 +56,10 @@
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:persistent="true" />
|
android:persistent="true" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="pref_backup_restore"
|
||||||
|
android:title="@string/backup_restore_title" />
|
||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
android:fragment="org.dslul.openboard.inputmethod.latin.settings.DebugSettingsFragment"
|
android:fragment="org.dslul.openboard.inputmethod.latin.settings.DebugSettingsFragment"
|
||||||
android:key="screen_debug"
|
android:key="screen_debug"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue