diff options
author | Harsh Shandilya <me@msfjarvis.dev> | 2021-12-10 14:51:05 +0530 |
---|---|---|
committer | Harsh Shandilya <me@msfjarvis.dev> | 2021-12-21 13:01:41 +0530 |
commit | a700e2a76622745890f21d499b380abce2031aab (patch) | |
tree | 2e69baba0cd6f278a8c40849896b857da514535f /app/src/main/java | |
parent | 0f837b003317970d50774df99bd474d3144120f8 (diff) |
app: remove XkPasswd generator
Diffstat (limited to 'app/src/main/java')
7 files changed, 1 insertions, 433 deletions
diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt index b22ee706..b1c66a0a 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt @@ -44,7 +44,6 @@ import dev.msfjarvis.aps.data.repo.PasswordRepository import dev.msfjarvis.aps.databinding.PasswordCreationActivityBinding import dev.msfjarvis.aps.ui.dialogs.OtpImportDialogFragment import dev.msfjarvis.aps.ui.dialogs.PasswordGeneratorDialogFragment -import dev.msfjarvis.aps.ui.dialogs.XkPasswordGeneratorDialogFragment import dev.msfjarvis.aps.util.autofill.AutofillPreferences import dev.msfjarvis.aps.util.autofill.DirectoryStructure import dev.msfjarvis.aps.util.crypto.GpgIdentifier @@ -361,8 +360,6 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB when (settings.getString(PreferenceKeys.PREF_KEY_PWGEN_TYPE) ?: KEY_PWGEN_TYPE_CLASSIC) { KEY_PWGEN_TYPE_CLASSIC -> PasswordGeneratorDialogFragment().show(supportFragmentManager, "generator") - KEY_PWGEN_TYPE_XKPASSWD -> - XkPasswordGeneratorDialogFragment().show(supportFragmentManager, "xkpwgenerator") } } @@ -594,7 +591,6 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB companion object { private const val KEY_PWGEN_TYPE_CLASSIC = "classic" - private const val KEY_PWGEN_TYPE_XKPASSWD = "xkpasswd" const val PASSWORD_RESULT_REQUEST_KEY = "PASSWORD_GENERATOR" const val OTP_RESULT_REQUEST_KEY = "OTP_IMPORT" const val RESULT = "RESULT" diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt index b99d5f6d..3aa24a9f 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt @@ -41,7 +41,6 @@ import dev.msfjarvis.aps.databinding.PasswordCreationActivityBinding import dev.msfjarvis.aps.injection.crypto.CryptoSet import dev.msfjarvis.aps.ui.dialogs.OtpImportDialogFragment import dev.msfjarvis.aps.ui.dialogs.PasswordGeneratorDialogFragment -import dev.msfjarvis.aps.ui.dialogs.XkPasswordGeneratorDialogFragment import dev.msfjarvis.aps.util.autofill.AutofillPreferences import dev.msfjarvis.aps.util.autofill.DirectoryStructure import dev.msfjarvis.aps.util.extensions.asLog @@ -291,8 +290,6 @@ class PasswordCreationActivityV2 : BasePgpActivity() { when (settings.getString(PreferenceKeys.PREF_KEY_PWGEN_TYPE) ?: KEY_PWGEN_TYPE_CLASSIC) { KEY_PWGEN_TYPE_CLASSIC -> PasswordGeneratorDialogFragment().show(supportFragmentManager, "generator") - KEY_PWGEN_TYPE_XKPASSWD -> - XkPasswordGeneratorDialogFragment().show(supportFragmentManager, "xkpwgenerator") } } @@ -469,7 +466,6 @@ class PasswordCreationActivityV2 : BasePgpActivity() { companion object { private const val KEY_PWGEN_TYPE_CLASSIC = "classic" - private const val KEY_PWGEN_TYPE_XKPASSWD = "xkpasswd" const val PASSWORD_RESULT_REQUEST_KEY = "PASSWORD_GENERATOR" const val OTP_RESULT_REQUEST_KEY = "OTP_IMPORT" const val RESULT = "RESULT" diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/dialogs/XkPasswordGeneratorDialogFragment.kt b/app/src/main/java/dev/msfjarvis/aps/ui/dialogs/XkPasswordGeneratorDialogFragment.kt deleted file mode 100644 index 7b2297ff..00000000 --- a/app/src/main/java/dev/msfjarvis/aps/ui/dialogs/XkPasswordGeneratorDialogFragment.kt +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package dev.msfjarvis.aps.ui.dialogs - -import android.app.Dialog -import android.content.Context -import android.content.SharedPreferences -import android.graphics.Typeface -import android.os.Bundle -import android.widget.Toast -import androidx.appcompat.app.AlertDialog -import androidx.core.content.edit -import androidx.core.os.bundleOf -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.setFragmentResult -import androidx.lifecycle.lifecycleScope -import com.github.michaelbull.result.fold -import com.github.michaelbull.result.getOr -import com.github.michaelbull.result.runCatching -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dev.msfjarvis.aps.R -import dev.msfjarvis.aps.databinding.FragmentXkpwgenBinding -import dev.msfjarvis.aps.ui.crypto.PasswordCreationActivity -import dev.msfjarvis.aps.util.extensions.asLog -import dev.msfjarvis.aps.util.extensions.getString -import dev.msfjarvis.aps.util.pwgenxkpwd.CapsType -import dev.msfjarvis.aps.util.pwgenxkpwd.PasswordBuilder -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.merge -import kotlinx.coroutines.flow.onEach -import logcat.LogPriority.ERROR -import logcat.logcat -import reactivecircus.flowbinding.android.widget.afterTextChanges -import reactivecircus.flowbinding.android.widget.selectionEvents - -@OptIn(ExperimentalCoroutinesApi::class) -class XkPasswordGeneratorDialogFragment : DialogFragment() { - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val builder = MaterialAlertDialogBuilder(requireContext()) - val callingActivity = requireActivity() - val inflater = callingActivity.layoutInflater - val binding = FragmentXkpwgenBinding.inflate(inflater) - val monoTypeface = Typeface.createFromAsset(callingActivity.assets, "fonts/sourcecodepro.ttf") - val prefs = callingActivity.getSharedPreferences("PasswordGenerator", Context.MODE_PRIVATE) - - builder.setView(binding.root) - - val previousStoredCapStyle: String = - runCatching { prefs.getString(PREF_KEY_CAPITALS_STYLE)!! }.getOr(DEFAULT_CAPS_STYLE) - - val lastCapitalsStyleIndex: Int = - runCatching { CapsType.valueOf(previousStoredCapStyle).ordinal }.getOr(DEFAULT_CAPS_INDEX) - binding.xkCapType.setSelection(lastCapitalsStyleIndex) - binding.xkNumWords.setText(prefs.getString(PREF_KEY_NUM_WORDS, DEFAULT_NUMBER_OF_WORDS)) - - binding.xkSeparator.setText(prefs.getString(PREF_KEY_SEPARATOR, DEFAULT_WORD_SEPARATOR)) - binding.xkNumberSymbolMask.setText( - prefs.getString(PREF_KEY_EXTRA_SYMBOLS_MASK, DEFAULT_EXTRA_SYMBOLS_MASK) - ) - - binding.xkPasswordText.typeface = monoTypeface - - builder.setPositiveButton(resources.getString(R.string.dialog_ok)) { _, _ -> - setPreferences(binding, prefs) - setFragmentResult( - PasswordCreationActivity.PASSWORD_RESULT_REQUEST_KEY, - bundleOf(PasswordCreationActivity.RESULT to "${binding.xkPasswordText.text}") - ) - } - - // flip neutral and negative buttons - builder.setNeutralButton(resources.getString(R.string.dialog_cancel)) { _, _ -> } - builder.setNegativeButton(resources.getString(R.string.pwgen_generate), null) - - val dialog = builder.setTitle(this.resources.getString(R.string.xkpwgen_title)).create() - - // make parameter changes reactive and automatically update passwords - merge( - binding.xkSeparator.afterTextChanges().skipInitialValue(), - binding.xkCapType.selectionEvents().skipInitialValue(), - binding.xkNumWords.afterTextChanges().skipInitialValue(), - binding.xkNumberSymbolMask.afterTextChanges().skipInitialValue(), - ) - .onEach { updatePassword(binding, prefs) } - .launchIn(lifecycleScope) - - dialog.setOnShowListener { - updatePassword(binding, prefs) - - dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener { - updatePassword(binding, prefs) - } - } - return dialog - } - - private fun updatePassword(binding: FragmentXkpwgenBinding, prefs: SharedPreferences) { - setPreferences(binding, prefs) - makeAndSetPassword(binding) - } - - private fun makeAndSetPassword(binding: FragmentXkpwgenBinding) { - PasswordBuilder(requireContext()) - .setNumberOfWords(binding.xkNumWords.text.toString().ifBlank { "0" }.toInt()) - .setMinimumWordLength(DEFAULT_MIN_WORD_LENGTH) - .setMaximumWordLength(DEFAULT_MAX_WORD_LENGTH) - .setSeparator(binding.xkSeparator.text.toString()) - .appendNumbers( - binding.xkNumberSymbolMask.text!!.count { c -> c == EXTRA_CHAR_PLACEHOLDER_DIGIT } - ) - .appendSymbols( - binding.xkNumberSymbolMask.text!!.count { c -> c == EXTRA_CHAR_PLACEHOLDER_SYMBOL } - ) - .setCapitalization(CapsType.valueOf(binding.xkCapType.selectedItem.toString())) - .create() - .fold( - success = { binding.xkPasswordText.text = it }, - failure = { e -> - Toast.makeText(requireActivity(), e.message, Toast.LENGTH_SHORT).show() - logcat("xkpw", ERROR) { e.asLog("failure generating xkpasswd") } - binding.xkPasswordText.text = FALLBACK_ERROR_PASS - }, - ) - } - - private fun setPreferences(binding: FragmentXkpwgenBinding, prefs: SharedPreferences) { - prefs.edit { - putString(PREF_KEY_CAPITALS_STYLE, binding.xkCapType.selectedItem.toString()) - putString(PREF_KEY_NUM_WORDS, binding.xkNumWords.text.toString()) - putString(PREF_KEY_SEPARATOR, binding.xkSeparator.text.toString()) - putString(PREF_KEY_EXTRA_SYMBOLS_MASK, binding.xkNumberSymbolMask.text.toString()) - } - } - - companion object { - - const val PREF_KEY_CAPITALS_STYLE = "pref_key_capitals_style" - const val PREF_KEY_NUM_WORDS = "pref_key_num_words" - const val PREF_KEY_SEPARATOR = "pref_key_separator" - const val PREF_KEY_EXTRA_SYMBOLS_MASK = "pref_key_xkpwgen_extra_symbols_mask" - val DEFAULT_CAPS_STYLE = CapsType.Sentence.name - val DEFAULT_CAPS_INDEX = CapsType.Sentence.ordinal - const val DEFAULT_NUMBER_OF_WORDS = "3" - const val DEFAULT_WORD_SEPARATOR = "." - const val DEFAULT_EXTRA_SYMBOLS_MASK = "ds" - const val DEFAULT_MIN_WORD_LENGTH = 3 - const val DEFAULT_MAX_WORD_LENGTH = 9 - const val FALLBACK_ERROR_PASS = "42" - const val EXTRA_CHAR_PLACEHOLDER_DIGIT = 'd' - const val EXTRA_CHAR_PLACEHOLDER_SYMBOL = 's' - } -} diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/settings/PasswordSettings.kt b/app/src/main/java/dev/msfjarvis/aps/ui/settings/PasswordSettings.kt index dced4fc8..c6da00b6 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/settings/PasswordSettings.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/settings/PasswordSettings.kt @@ -6,78 +6,20 @@ package dev.msfjarvis.aps.ui.settings import android.text.InputType -import android.widget.Toast -import androidx.activity.result.contract.ActivityResultContracts -import androidx.core.content.edit import androidx.fragment.app.FragmentActivity -import de.Maxr1998.modernpreferences.Preference import de.Maxr1998.modernpreferences.PreferenceScreen import de.Maxr1998.modernpreferences.helpers.checkBox import de.Maxr1998.modernpreferences.helpers.editText -import de.Maxr1998.modernpreferences.helpers.onCheckedChange -import de.Maxr1998.modernpreferences.helpers.onClick import de.Maxr1998.modernpreferences.helpers.onSelectionChange import de.Maxr1998.modernpreferences.helpers.singleChoice -import de.Maxr1998.modernpreferences.preferences.CheckBoxPreference import de.Maxr1998.modernpreferences.preferences.choice.SelectionItem import dev.msfjarvis.aps.R -import dev.msfjarvis.aps.util.extensions.getString -import dev.msfjarvis.aps.util.extensions.sharedPrefs -import dev.msfjarvis.aps.util.extensions.unsafeLazy -import dev.msfjarvis.aps.util.pwgenxkpwd.XkpwdDictionary import dev.msfjarvis.aps.util.settings.PreferenceKeys -import java.io.File class PasswordSettings(private val activity: FragmentActivity) : SettingsProvider { - private val sharedPrefs by unsafeLazy { activity.sharedPrefs } - private val storeCustomXkpwdDictionaryAction = - activity.registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri -> - if (uri == null) return@registerForActivityResult - - Toast.makeText( - activity, - activity.resources.getString(R.string.xkpwgen_custom_dict_imported, uri.path), - Toast.LENGTH_SHORT - ) - .show() - - sharedPrefs.edit { putString(PreferenceKeys.PREF_KEY_CUSTOM_DICT, uri.toString()) } - - val inputStream = activity.contentResolver.openInputStream(uri) - val customDictFile = - File(activity.filesDir.toString(), XkpwdDictionary.XKPWD_CUSTOM_DICT_FILE).outputStream() - inputStream?.copyTo(customDictFile, 1024) - inputStream?.close() - customDictFile.close() - } - override fun provideSettings(builder: PreferenceScreen.Builder) { builder.apply { - val customDictPref = - CheckBoxPreference(PreferenceKeys.PREF_KEY_IS_CUSTOM_DICT).apply { - titleRes = R.string.pref_xkpwgen_custom_wordlist_enabled_title - summaryRes = R.string.pref_xkpwgen_custom_dict_summary_off - summaryOnRes = R.string.pref_xkpwgen_custom_dict_summary_on - visible = sharedPrefs.getString(PreferenceKeys.PREF_KEY_PWGEN_TYPE) == "xkpasswd" - onCheckedChange { - requestRebind() - true - } - } - val customDictPathPref = - Preference(PreferenceKeys.PREF_KEY_CUSTOM_DICT).apply { - dependency = PreferenceKeys.PREF_KEY_IS_CUSTOM_DICT - titleRes = R.string.pref_xkpwgen_custom_dict_picker_title - summary = - sharedPrefs.getString(PreferenceKeys.PREF_KEY_CUSTOM_DICT) - ?: activity.resources.getString(R.string.pref_xkpwgen_custom_dict_picker_summary) - visible = sharedPrefs.getString(PreferenceKeys.PREF_KEY_PWGEN_TYPE) == "xkpasswd" - onClick { - storeCustomXkpwdDictionaryAction.launch(arrayOf("*/*")) - true - } - } val values = activity.resources.getStringArray(R.array.pwgen_provider_values) val labels = activity.resources.getStringArray(R.array.pwgen_provider_labels) val items = values.zip(labels).map { SelectionItem(it.first, it.second, null) } @@ -87,19 +29,8 @@ class PasswordSettings(private val activity: FragmentActivity) : SettingsProvide ) { initialSelection = "classic" titleRes = R.string.pref_password_generator_type_title - onSelectionChange { selection -> - val xkpasswdEnabled = selection == "xkpasswd" - customDictPathPref.visible = xkpasswdEnabled - customDictPref.visible = xkpasswdEnabled - customDictPref.requestRebind() - customDictPathPref.requestRebind() - true - } + onSelectionChange { true } } - // We initialize them early and add them manually to be able to manually force a rebind - // when the password generator type is changed. - addPreferenceItem(customDictPref) - addPreferenceItem(customDictPathPref) editText(PreferenceKeys.GENERAL_SHOW_TIME) { titleRes = R.string.pref_clipboard_timeout_title summaryProvider = diff --git a/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/CapsType.kt b/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/CapsType.kt deleted file mode 100644 index 69a4692d..00000000 --- a/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/CapsType.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package dev.msfjarvis.aps.util.pwgenxkpwd - -enum class CapsType { - lowercase, - UPPERCASE, - TitleCase, - Sentence, - As_iS -} diff --git a/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/PasswordBuilder.kt b/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/PasswordBuilder.kt deleted file mode 100644 index af8ac5c2..00000000 --- a/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/PasswordBuilder.kt +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package dev.msfjarvis.aps.util.pwgenxkpwd - -import android.content.Context -import com.github.michaelbull.result.Result -import com.github.michaelbull.result.runCatching -import dev.msfjarvis.aps.R -import dev.msfjarvis.aps.util.pwgen.PasswordGenerator.PasswordGeneratorException -import dev.msfjarvis.aps.util.pwgen.secureRandomCharacter -import dev.msfjarvis.aps.util.pwgen.secureRandomElement -import dev.msfjarvis.aps.util.pwgen.secureRandomNumber -import java.util.Locale - -class PasswordBuilder(ctx: Context) { - - private var numSymbols = 0 - private var isAppendSymbolsSeparator = false - private var context = ctx - private var numWords = 3 - private var maxWordLength = 9 - private var minWordLength = 5 - private var separator = "." - private var capsType = CapsType.Sentence - private var prependDigits = 0 - private var numDigits = 0 - private var isPrependWithSeparator = false - private var isAppendNumberSeparator = false - - fun setNumberOfWords(amount: Int) = apply { numWords = amount } - - fun setMinimumWordLength(min: Int) = apply { minWordLength = min } - - fun setMaximumWordLength(max: Int) = apply { maxWordLength = max } - - fun setSeparator(separator: String) = apply { this.separator = separator } - - fun setCapitalization(capitalizationScheme: CapsType) = apply { capsType = capitalizationScheme } - - @JvmOverloads - fun prependNumbers(numDigits: Int, addSeparator: Boolean = true) = apply { - prependDigits = numDigits - isPrependWithSeparator = addSeparator - } - - @JvmOverloads - fun appendNumbers(numDigits: Int, addSeparator: Boolean = false) = apply { - this.numDigits = numDigits - isAppendNumberSeparator = addSeparator - } - - @JvmOverloads - fun appendSymbols(numSymbols: Int, addSeparator: Boolean = false) = apply { - this.numSymbols = numSymbols - isAppendSymbolsSeparator = addSeparator - } - - private fun generateRandomNumberSequence(totalNumbers: Int): String { - val numbers = StringBuilder(totalNumbers) - for (i in 0 until totalNumbers) { - numbers.append(secureRandomNumber(10)) - } - return numbers.toString() - } - - private fun generateRandomSymbolSequence(numSymbols: Int): String { - val numbers = StringBuilder(numSymbols) - for (i in 0 until numSymbols) { - numbers.append(SYMBOLS.secureRandomCharacter()) - } - return numbers.toString() - } - - @OptIn(ExperimentalStdlibApi::class) - fun create(): Result<String, Throwable> { - val wordBank = mutableListOf<String>() - val password = StringBuilder() - - if (prependDigits != 0) { - password.append(generateRandomNumberSequence(prependDigits)) - if (isPrependWithSeparator) { - password.append(separator) - } - } - return runCatching { - val dictionary = XkpwdDictionary(context) - val words = dictionary.words - for (wordLength in minWordLength..maxWordLength) { - wordBank.addAll(words[wordLength] ?: emptyList()) - } - - if (wordBank.size == 0) { - throw PasswordGeneratorException( - context.getString(R.string.xkpwgen_builder_error, minWordLength, maxWordLength) - ) - } - - for (i in 0 until numWords) { - val candidate = wordBank.secureRandomElement() - val s = - when (capsType) { - CapsType.UPPERCASE -> candidate.uppercase(Locale.getDefault()) - CapsType.Sentence -> - if (i == 0) - candidate.replaceFirstChar { - if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() - } - else candidate - CapsType.TitleCase -> - candidate.replaceFirstChar { - if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() - } - CapsType.lowercase -> candidate.lowercase(Locale.getDefault()) - CapsType.As_iS -> candidate - } - password.append(s) - if (i + 1 < numWords) { - password.append(separator) - } - } - if (numDigits != 0) { - if (isAppendNumberSeparator) { - password.append(separator) - } - password.append(generateRandomNumberSequence(numDigits)) - } - if (numSymbols != 0) { - if (isAppendSymbolsSeparator) { - password.append(separator) - } - password.append(generateRandomSymbolSequence(numSymbols)) - } - password.toString() - } - } - - companion object { - - private const val SYMBOLS = "!@\$%^&*-_+=:|~?/.;#" - } -} diff --git a/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/XkpwdDictionary.kt b/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/XkpwdDictionary.kt deleted file mode 100644 index 25162378..00000000 --- a/app/src/main/java/dev/msfjarvis/aps/util/pwgenxkpwd/XkpwdDictionary.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package dev.msfjarvis.aps.util.pwgenxkpwd - -import android.content.Context -import dev.msfjarvis.aps.R -import dev.msfjarvis.aps.util.extensions.getString -import dev.msfjarvis.aps.util.extensions.sharedPrefs -import dev.msfjarvis.aps.util.settings.PreferenceKeys -import java.io.File - -class XkpwdDictionary(context: Context) { - - val words: Map<Int, List<String>> - - init { - val prefs = context.sharedPrefs - val uri = prefs.getString(PreferenceKeys.PREF_KEY_CUSTOM_DICT) ?: "" - val customDictFile = File(context.filesDir, XKPWD_CUSTOM_DICT_FILE) - - val lines = - if (prefs.getBoolean(PreferenceKeys.PREF_KEY_IS_CUSTOM_DICT, false) && - uri.isNotEmpty() && - customDictFile.canRead() - ) { - customDictFile.readLines() - } else { - context.resources.openRawResource(R.raw.xkpwdict).bufferedReader().readLines() - } - - words = - lines.asSequence().map { it.trim() }.filter { it.isNotEmpty() && !it.contains(' ') }.groupBy { - it.length - } - } - - companion object { - - const val XKPWD_CUSTOM_DICT_FILE = "custom_dict.txt" - } -} |