mirror of
https://github.com/android-password-store/Android-Password-Store
synced 2025-08-29 13:27:46 +00:00
app: add diceware generator dialog
This commit is contained in:
parent
0e8f899434
commit
fd46f1f0ba
@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
package dev.msfjarvis.aps.injection.prefs
|
||||
|
||||
import javax.inject.Qualifier
|
||||
|
||||
@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class PasswordGeneratorPreferences
|
@ -32,6 +32,11 @@ class PreferenceModule {
|
||||
)
|
||||
}
|
||||
|
||||
@[Provides PasswordGeneratorPreferences Reusable]
|
||||
fun providePwgenPreferences(@ApplicationContext context: Context): SharedPreferences {
|
||||
return provideBaseEncryptedPreferences(context, "pwgen_preferences")
|
||||
}
|
||||
|
||||
@Provides
|
||||
@SettingsPreferences
|
||||
@Reusable
|
||||
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.AlertDialog
|
||||
import android.app.Dialog
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
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.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dev.msfjarvis.aps.R
|
||||
import dev.msfjarvis.aps.databinding.FragmentPwgenDicewareBinding
|
||||
import dev.msfjarvis.aps.injection.prefs.PasswordGeneratorPreferences
|
||||
import dev.msfjarvis.aps.passgen.diceware.DicewarePassphraseGenerator
|
||||
import dev.msfjarvis.aps.ui.crypto.PasswordCreationActivity
|
||||
import dev.msfjarvis.aps.util.extensions.getString
|
||||
import dev.msfjarvis.aps.util.settings.PreferenceKeys.DICEWARE_LENGTH
|
||||
import dev.msfjarvis.aps.util.settings.PreferenceKeys.DICEWARE_SEPARATOR
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.widget.afterTextChanges
|
||||
|
||||
@AndroidEntryPoint
|
||||
class DicewarePasswordGeneratorDialogFragment : DialogFragment() {
|
||||
|
||||
@Inject lateinit var dicewareGenerator: DicewarePassphraseGenerator
|
||||
@Inject @PasswordGeneratorPreferences lateinit var prefs: SharedPreferences
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||
val binding = FragmentPwgenDicewareBinding.inflate(layoutInflater)
|
||||
val monoTypeface = Typeface.createFromAsset(requireContext().assets, "fonts/sourcecodepro.ttf")
|
||||
binding.passwordSeparatorText.setText(prefs.getString(DICEWARE_SEPARATOR) ?: "-")
|
||||
binding.passwordLengthText.setText(prefs.getInt(DICEWARE_LENGTH, 5).toString())
|
||||
binding.passwordText.typeface = monoTypeface
|
||||
builder.setView(binding.root)
|
||||
merge(
|
||||
binding.passwordLengthText.afterTextChanges(),
|
||||
binding.passwordSeparatorText.afterTextChanges(),
|
||||
)
|
||||
.onEach { generatePassword(binding) }
|
||||
.launchIn(lifecycleScope)
|
||||
return builder
|
||||
.run {
|
||||
setTitle(R.string.pwgen_title)
|
||||
setPositiveButton(R.string.dialog_ok) { _, _ ->
|
||||
setFragmentResult(
|
||||
PasswordCreationActivity.PASSWORD_RESULT_REQUEST_KEY,
|
||||
bundleOf(PasswordCreationActivity.RESULT to "${binding.passwordText.text}")
|
||||
)
|
||||
}
|
||||
setNeutralButton(R.string.dialog_cancel) { _, _ -> }
|
||||
setNegativeButton(R.string.pwgen_generate, null)
|
||||
create()
|
||||
}
|
||||
.apply {
|
||||
setOnShowListener {
|
||||
generatePassword(binding)
|
||||
getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener { generatePassword(binding) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generatePassword(binding: FragmentPwgenDicewareBinding) {
|
||||
val length = binding.passwordLengthText.text?.toString()?.toIntOrNull() ?: 5
|
||||
val separator = binding.passwordSeparatorText.text?.toString()?.getOrNull(0) ?: '-'
|
||||
setPreferences(length, separator)
|
||||
binding.passwordText.text = dicewareGenerator.generatePassphrase(length, separator)
|
||||
}
|
||||
|
||||
private fun setPreferences(length: Int, separator: Char) {
|
||||
prefs.edit {
|
||||
putInt(DICEWARE_LENGTH, length)
|
||||
putString(DICEWARE_SEPARATOR, separator.toString())
|
||||
}
|
||||
}
|
||||
}
|
@ -82,4 +82,7 @@ object PreferenceKeys {
|
||||
const val PROXY_PASSWORD = "proxy_password"
|
||||
|
||||
const val REBASE_ON_PULL = "rebase_on_pull"
|
||||
|
||||
const val DICEWARE_SEPARATOR = "diceware_separator"
|
||||
const val DICEWARE_LENGTH = "diceware_length"
|
||||
}
|
||||
|
73
app/src/main/res/layout/fragment_pwgen_diceware.xml
Normal file
73
app/src/main/res/layout/fragment_pwgen_diceware.xml
Normal file
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
|
||||
~ SPDX-License-Identifier: GPL-3.0-only
|
||||
-->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingRight="24dp"
|
||||
android:paddingBottom="20dp">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/password_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/password_length"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:hint="@string/pwgen_length"
|
||||
android:labelFor="@id/password_length_text"
|
||||
app:hintAnimationEnabled="true"
|
||||
app:hintEnabled="true"
|
||||
app:layout_constraintEnd_toStartOf="@id/password_separator"
|
||||
app:layout_constraintHorizontal_weight="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/password_text">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/password_length_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="number"
|
||||
android:maxLength="2" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/password_separator"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/pwgen_separator"
|
||||
android:labelFor="@id/password_separator_text"
|
||||
app:hintAnimationEnabled="true"
|
||||
app:hintEnabled="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_weight="0.5"
|
||||
app:layout_constraintStart_toEndOf="@id/password_length"
|
||||
app:layout_constraintTop_toBottomOf="@id/password_text">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/password_separator_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autofillHints=""
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="text"
|
||||
android:maxLength="1" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
x
Reference in New Issue
Block a user