Make password generator parameter changes reactive (#1480)
* Make XkPassword generator reactive * Handle empty strings * Make password generator reactive * Sync changelog for 1.13.5 release * Add to changelog
This commit is contained in:
parent
1b54e679b7
commit
1738364d2f
5 changed files with 60 additions and 9 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -30,11 +30,17 @@ All notable changes to this project will be documented in this file.
|
|||
- Using the `git://` protocol in the server URL now presents an explicit discouragement rather than a generic error
|
||||
- Encrypted data is no longer ASCII armored, bringing it in line with `pass`
|
||||
- Removed Bromite from supported Autofill browsers, since they [disable Android autofill](https://github.com/bromite/bromite/blob/master/FAQ.md#does-bromite-support-the-android-autofill-framework).
|
||||
- Changing password generator parameters now automatically updates the password without needing to press the 'Generate' button again
|
||||
|
||||
## [1.13.4] - 2021-03-20
|
||||
## [1.13.5] - 2021-07-28
|
||||
|
||||
### Fixed
|
||||
|
||||
- When prompted to select a GPG key during onboarding, the app would crash if the user did not make a selection in OpenKeychain
|
||||
- Certain apps had incorrect Autofill hints which would crash the app
|
||||
|
||||
## [1.13.4] - 2021-03-20
|
||||
|
||||
- Fix support for ECDSA SSH keys and support AES-GCM
|
||||
- Fix a couple issues with Autofill
|
||||
|
||||
|
@ -448,7 +454,9 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
- Fix elements overlapping.
|
||||
|
||||
[Unreleased]: https://github.com/android-password-store/Android-Password-Store/compare/v1.13.4...HEAD
|
||||
[Unreleased]: https://github.com/android-password-store/Android-Password-Store/compare/v1.13.5...release-1.13
|
||||
|
||||
[1.13.5]: https://github.com/android-password-store/Android-Password-Store/compare/v1.13.4...v1.13.5
|
||||
|
||||
[1.13.4]: https://github.com/android-password-store/Android-Password-Store/compare/v1.13.3...v1.13.4
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ dependencies {
|
|||
implementation(libs.thirdparty.bouncycastle)
|
||||
implementation(libs.thirdparty.eddsa)
|
||||
implementation(libs.thirdparty.fastscroll)
|
||||
implementation(libs.thirdparty.flowbinding.android)
|
||||
implementation(libs.thirdparty.jgit) {
|
||||
exclude(group = "org.apache.httpcomponents", module = "httpclient")
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import androidx.appcompat.widget.AppCompatTextView
|
|||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.github.michaelbull.result.getOrElse
|
||||
import com.github.michaelbull.result.runCatching
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
@ -28,7 +29,14 @@ import dev.msfjarvis.aps.util.pwgen.PasswordGenerator.generate
|
|||
import dev.msfjarvis.aps.util.pwgen.PasswordGenerator.setPrefs
|
||||
import dev.msfjarvis.aps.util.pwgen.PasswordOption
|
||||
import dev.msfjarvis.aps.util.settings.PreferenceKeys
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.widget.afterTextChanges
|
||||
import reactivecircus.flowbinding.android.widget.checkedChanges
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class PasswordGeneratorDialogFragment : DialogFragment() {
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
|
@ -49,9 +57,21 @@ class PasswordGeneratorDialogFragment : DialogFragment() {
|
|||
binding.lowercase.isChecked = !prefs.getBoolean(PasswordOption.NoLowercaseLetters.key, false)
|
||||
binding.ambiguous.isChecked = !prefs.getBoolean(PasswordOption.NoAmbiguousCharacters.key, false)
|
||||
binding.pronounceable.isChecked = !prefs.getBoolean(PasswordOption.FullyRandom.key, true)
|
||||
|
||||
binding.lengthNumber.setText(prefs.getInt(PreferenceKeys.LENGTH, 20).toString())
|
||||
binding.passwordText.typeface = monoTypeface
|
||||
|
||||
merge(
|
||||
binding.numerals.checkedChanges().skipInitialValue(),
|
||||
binding.symbols.checkedChanges().skipInitialValue(),
|
||||
binding.uppercase.checkedChanges().skipInitialValue(),
|
||||
binding.lowercase.checkedChanges().skipInitialValue(),
|
||||
binding.ambiguous.checkedChanges().skipInitialValue(),
|
||||
binding.pronounceable.checkedChanges().skipInitialValue(),
|
||||
binding.lengthNumber.afterTextChanges().skipInitialValue(),
|
||||
)
|
||||
.onEach { generate(binding.passwordText) }
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
return builder
|
||||
.run {
|
||||
setTitle(R.string.pwgen_title)
|
||||
|
|
|
@ -15,6 +15,7 @@ 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.ajalt.timberkt.Timber.tag
|
||||
import com.github.michaelbull.result.fold
|
||||
import com.github.michaelbull.result.getOr
|
||||
|
@ -26,8 +27,14 @@ import dev.msfjarvis.aps.ui.crypto.PasswordCreationActivity
|
|||
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 reactivecircus.flowbinding.android.widget.afterTextChanges
|
||||
import reactivecircus.flowbinding.android.widget.selectionEvents
|
||||
|
||||
/** A placeholder fragment containing a simple view. */
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class XkPasswordGeneratorDialogFragment : DialogFragment() {
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
|
@ -69,21 +76,34 @@ class XkPasswordGeneratorDialogFragment : DialogFragment() {
|
|||
|
||||
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 {
|
||||
setPreferences(binding, prefs)
|
||||
makeAndSetPassword(binding)
|
||||
updatePassword(binding, prefs)
|
||||
|
||||
dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener {
|
||||
setPreferences(binding, prefs)
|
||||
makeAndSetPassword(binding)
|
||||
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(Integer.valueOf(binding.xkNumWords.text.toString()))
|
||||
.setNumberOfWords(binding.xkNumWords.text.toString().ifBlank { "0" }.toInt())
|
||||
.setMinimumWordLength(DEFAULT_MIN_WORD_LENGTH)
|
||||
.setMaximumWordLength(DEFAULT_MAX_WORD_LENGTH)
|
||||
.setSeparator(binding.xkSeparator.text.toString())
|
||||
|
|
|
@ -5,6 +5,7 @@ androidx_test = "1.4.0"
|
|||
compose = "1.1.0-alpha01"
|
||||
composeSnapshot = "-"
|
||||
coroutines = "1.5.1"
|
||||
flowbinding = "1.2.0"
|
||||
hilt = "2.38.1"
|
||||
kotlin = "1.5.21"
|
||||
lifecycle = "2.4.0-alpha03"
|
||||
|
@ -69,6 +70,7 @@ thirdparty-bouncycastle = "org.bouncycastle:bcprov-jdk15on:1.69"
|
|||
thirdparty-commons_codec = "commons-codec:commons-codec:1.14"
|
||||
thirdparty-eddsa = "net.i2p.crypto:eddsa:0.3.0"
|
||||
thirdparty-fastscroll = "me.zhanghai.android.fastscroll:library:1.1.7"
|
||||
thirdparty-flowbinding-android = { module = "io.github.reactivecircus.flowbinding:flowbinding-android", version.ref = "flowbinding" }
|
||||
thirdparty-jgit = "org.eclipse.jgit:org.eclipse.jgit:3.7.1.201504261725-r"
|
||||
thirdparty-kotlinResult = "com.michael-bull.kotlin-result:kotlin-result:1.1.12"
|
||||
thirdparty-leakcanary = "com.squareup.leakcanary:leakcanary-android:2.7"
|
||||
|
|
Loading…
Reference in a new issue