Added the options to change the Security Lock option between PIN and None, and force the UI to show the correct one when it is changed.
parent
b4965d8a01
commit
e8e1259314
|
@ -18,8 +18,9 @@ abstract class BaseSecurityLockDialog : DialogFragment() {
|
|||
/** Used to denote that the user is in the step of creating the preferred security lock option */
|
||||
const val STEP_SECURITY_LOCK_CREATE = 1
|
||||
|
||||
/** Used to denote that the user is in the step of confirming the newly created security lock option */
|
||||
private const val STEP_SECURITY_LOCK_CONFIRM = 2
|
||||
/** Used to denote that the user is in the step of confirming the newly created security lock option,
|
||||
* this option should only be used internally */
|
||||
const val STEP_SECURITY_LOCK_CONFIRM = 2
|
||||
|
||||
/** Used to denote that the user is in the step of verifying the current security lock option, to give
|
||||
* permission to do a security constrained action like sending a transaction or trying to change the
|
||||
|
@ -45,10 +46,10 @@ abstract class BaseSecurityLockDialog : DialogFragment() {
|
|||
protected var mCallback: OnPINPatternEnteredListener? = null
|
||||
|
||||
/** Keeps track of the current step, can be create, confirm of verify */
|
||||
protected var currentStep: Int = 1
|
||||
protected var currentStep: Int = -1
|
||||
|
||||
/** Used so the calling object knows what was the intention to ask for the Security Lock */
|
||||
protected var actionIdentifier: Int = 0
|
||||
protected var actionIdentifier: Int = -1
|
||||
|
||||
/** Keeps track of all RxJava disposables, to make sure they are all disposed when the fragment is destroyed */
|
||||
protected var mDisposables = CompositeDisposable()
|
||||
|
@ -64,9 +65,9 @@ abstract class BaseSecurityLockDialog : DialogFragment() {
|
|||
currentEncryptedPINPattern = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getString(Constants.KEY_ENCRYPTED_PIN, "")?.trim()
|
||||
|
||||
currentStep = arguments?.getInt(KEY_STEP_SECURITY_LOCK) ?: 0
|
||||
currentStep = arguments?.getInt(KEY_STEP_SECURITY_LOCK) ?: -1
|
||||
|
||||
actionIdentifier = arguments?.getInt(KEY_ACTION_IDENTIFIER) ?: 0
|
||||
actionIdentifier = arguments?.getInt(KEY_ACTION_IDENTIFIER) ?: -1
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package cy.agorise.bitsybitshareswallet.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import cy.agorise.bitsybitshareswallet.R
|
||||
import cy.agorise.bitsybitshareswallet.utils.Constants
|
||||
import cy.agorise.bitsybitshareswallet.utils.CryptoUtils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import kotlinx.android.synthetic.main.dialog_pin_security_lock.*
|
||||
|
@ -25,23 +27,50 @@ class PINSecurityLockDialog : BaseSecurityLockDialog() {
|
|||
return inflater.inflate(R.layout.dialog_pin_security_lock, container, false)
|
||||
}
|
||||
|
||||
private var newPIN = ""
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setupScreen()
|
||||
|
||||
// Listens to the event when the user clicks the 'Enter' button in the keyboard and acts accordingly
|
||||
tietPIN.setOnEditorActionListener { v, actionId, _ ->
|
||||
var handled = false
|
||||
if (actionId == EditorInfo.IME_ACTION_GO) {
|
||||
val encryptedPIN = CryptoUtils.encrypt(v.context, v.text.toString()).trim()
|
||||
|
||||
if (currentStep == STEP_SECURITY_LOCK_VERIFY) {
|
||||
// The user just wants to verify the current encrypted PIN/Pattern
|
||||
val encryptedPIN = CryptoUtils.encrypt(v.context, v.text.toString()).trim()
|
||||
|
||||
if (encryptedPIN == currentEncryptedPINPattern) {
|
||||
// PIN is correct, proceed
|
||||
dismiss()
|
||||
mCallback?.onPINPatternEntered(actionIdentifier)
|
||||
} else {
|
||||
tilPIN.error = "Wrong PIN"
|
||||
tilPIN.error = getString(R.string.error__wrong_pin)
|
||||
}
|
||||
} else if (currentStep == STEP_SECURITY_LOCK_CREATE) {
|
||||
// The user is trying to create a new PIN
|
||||
if (v.text.toString().trim().length >= Constants.MIN_PIN_LENGTH) {
|
||||
// Proceed to the next step only if the PIN has the min length
|
||||
newPIN = v.text.toString().trim()
|
||||
currentStep = STEP_SECURITY_LOCK_CONFIRM
|
||||
setupScreen()
|
||||
}
|
||||
} else if (currentStep == STEP_SECURITY_LOCK_CONFIRM) {
|
||||
val pinConfirm = v.text.toString().trim()
|
||||
if (pinConfirm != newPIN) {
|
||||
tvTitle.text = getString(R.string.title__pins_dont_match)
|
||||
} else {
|
||||
val encryptedPIN = CryptoUtils.encrypt(v.context, v.text.toString()).trim()
|
||||
|
||||
// Stores the newly selected PIN, encrypted
|
||||
PreferenceManager.getDefaultSharedPreferences(v.context).edit()
|
||||
.putString(Constants.KEY_ENCRYPTED_PIN, encryptedPIN)
|
||||
.putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 0).apply() // 0 -> PIN
|
||||
|
||||
dismiss()
|
||||
mCallback?.onPINPatternChanged()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,11 +79,47 @@ class PINSecurityLockDialog : BaseSecurityLockDialog() {
|
|||
handled
|
||||
}
|
||||
|
||||
// Use RxBindings to clear the error when the user edits the PIN
|
||||
mDisposables.add(
|
||||
tietPIN.textChanges()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { tilPIN.isErrorEnabled = false }
|
||||
.subscribe {
|
||||
if (currentStep == STEP_SECURITY_LOCK_VERIFY) {
|
||||
// Make sure the error is removed when the user types again
|
||||
tilPIN.isErrorEnabled = false
|
||||
} else if (currentStep == STEP_SECURITY_LOCK_CREATE) {
|
||||
// Show the min length requirement for the PIN only when it has not been fulfilled
|
||||
if (it.trim().length >= Constants.MIN_PIN_LENGTH) {
|
||||
tilPIN.helperText = ""
|
||||
} else {
|
||||
tilPIN.helperText = getString(R.string.msg__min_pin_length)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupScreen() {
|
||||
when (currentStep) {
|
||||
STEP_SECURITY_LOCK_VERIFY -> {
|
||||
tvTitle.text = getString(R.string.title__re_enter_your_pin)
|
||||
tvSubTitle.text = getString(R.string.msg__enter_your_pin)
|
||||
tilPIN.helperText = ""
|
||||
tilPIN.isErrorEnabled = false
|
||||
}
|
||||
STEP_SECURITY_LOCK_CREATE -> {
|
||||
tvTitle.text = getString(R.string.title__set_bitsy_screen_lock)
|
||||
tvSubTitle.text = getString(R.string.msg__set_bitsy_pin)
|
||||
tilPIN.helperText = getString(R.string.msg__min_pin_length)
|
||||
tilPIN.isErrorEnabled = false
|
||||
}
|
||||
STEP_SECURITY_LOCK_CONFIRM -> {
|
||||
tvTitle.text = getString(R.string.title__re_enter_your_pin)
|
||||
tvSubTitle.text = ""
|
||||
tvSubTitle.visibility = View.GONE
|
||||
tietPIN.setText("")
|
||||
tilPIN.helperText = ""
|
||||
tilPIN.isErrorEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@ import cy.agorise.bitsybitshareswallet.adapters.FullNodesAdapter
|
|||
import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository
|
||||
import cy.agorise.bitsybitshareswallet.utils.Constants
|
||||
import cy.agorise.bitsybitshareswallet.utils.CryptoUtils
|
||||
import cy.agorise.bitsybitshareswallet.utils.toast
|
||||
import cy.agorise.graphenej.BrainKey
|
||||
import cy.agorise.graphenej.api.android.NetworkService
|
||||
import cy.agorise.graphenej.api.android.RxBus
|
||||
|
@ -108,15 +107,12 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
|
|||
// 1 -> Pattern
|
||||
// 2 -> None
|
||||
|
||||
btnViewBrainKey.setOnClickListener {
|
||||
if (!verifySecurityLock(securityLockSelected, ACTION_SHOW_BRAINKEY))
|
||||
getBrainkey()
|
||||
}
|
||||
|
||||
tvSecurityLockSelected.text = resources.getStringArray(R.array.security_lock_options)[securityLockSelected]
|
||||
|
||||
tvSecurityLock.setOnClickListener { onSecurityLockTextSelected(securityLockSelected) }
|
||||
tvSecurityLockSelected.setOnClickListener { onSecurityLockTextSelected(securityLockSelected) }
|
||||
tvSecurityLock.setOnClickListener { onSecurityLockTextSelected() }
|
||||
tvSecurityLockSelected.setOnClickListener { onSecurityLockTextSelected() }
|
||||
|
||||
btnViewBrainKey.setOnClickListener { onShowBrainKeyButtonSelected() }
|
||||
|
||||
// Connect to the RxBus, which receives events from the NetworkService
|
||||
mDisposables.add(
|
||||
|
@ -216,7 +212,14 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
|
|||
}
|
||||
}
|
||||
|
||||
private fun onSecurityLockTextSelected(securityLockSelected: Int) {
|
||||
private fun onSecurityLockTextSelected() {
|
||||
val securityLockSelected = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getInt(Constants.KEY_SECURITY_LOCK_SELECTED, 0)
|
||||
// Security Lock Options
|
||||
// 0 -> PIN
|
||||
// 1 -> Pattern
|
||||
// 2 -> None
|
||||
|
||||
if (!verifySecurityLock(securityLockSelected, ACTION_CHANGE_SECURITY_LOCK))
|
||||
showChooseSecurityLockDialog()
|
||||
}
|
||||
|
@ -231,7 +234,7 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
|
|||
*/
|
||||
private fun verifySecurityLock(securityLockSelected: Int, actionIdentifier: Int): Boolean {
|
||||
return when (securityLockSelected) {
|
||||
0 /* PIN */ -> {
|
||||
0 -> { /* PIN */
|
||||
val pinFrag = PINSecurityLockDialog()
|
||||
val args = Bundle()
|
||||
args.putInt(BaseSecurityLockDialog.KEY_STEP_SECURITY_LOCK,
|
||||
|
@ -241,7 +244,7 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
|
|||
pinFrag.show(childFragmentManager, "pin_security_lock_tag")
|
||||
true
|
||||
}
|
||||
1 /* Pattern */ -> {
|
||||
1 -> { /* Pattern */
|
||||
|
||||
true
|
||||
}
|
||||
|
@ -260,7 +263,15 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
|
|||
}
|
||||
|
||||
override fun onPINPatternChanged() {
|
||||
// Obtain the new Security Lock Option selected and display it in the screen
|
||||
val securityLockSelected = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getInt(Constants.KEY_SECURITY_LOCK_SELECTED, 0)
|
||||
// Security Lock Options
|
||||
// 0 -> PIN
|
||||
// 1 -> Pattern
|
||||
// 2 -> None
|
||||
|
||||
tvSecurityLockSelected.text = resources.getStringArray(R.array.security_lock_options)[securityLockSelected]
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -271,12 +282,44 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
|
|||
MaterialDialog(it).show {
|
||||
title(R.string.title__security_dialog)
|
||||
listItems(R.array.security_lock_options) {dialog, index, text ->
|
||||
dialog.context.toast("$text selected!")
|
||||
when (index) {
|
||||
0 -> { /* PIN */
|
||||
val pinFrag = PINSecurityLockDialog()
|
||||
val args = Bundle()
|
||||
args.putInt(BaseSecurityLockDialog.KEY_STEP_SECURITY_LOCK,
|
||||
BaseSecurityLockDialog.STEP_SECURITY_LOCK_CREATE)
|
||||
args.putInt(BaseSecurityLockDialog.KEY_ACTION_IDENTIFIER, -1)
|
||||
pinFrag.arguments = args
|
||||
pinFrag.show(childFragmentManager, "pin_security_lock_tag")
|
||||
}
|
||||
1 -> { /* Pattern */
|
||||
|
||||
}
|
||||
else -> { /* None */
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit()
|
||||
.putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 2).apply() // 2 -> None
|
||||
|
||||
// Call this function to update the UI
|
||||
onPINPatternChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onShowBrainKeyButtonSelected() {
|
||||
val securityLockSelected = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getInt(Constants.KEY_SECURITY_LOCK_SELECTED, 0)
|
||||
// Security Lock Options
|
||||
// 0 -> PIN
|
||||
// 1 -> Pattern
|
||||
// 2 -> None
|
||||
|
||||
if (!verifySecurityLock(securityLockSelected, ACTION_SHOW_BRAINKEY))
|
||||
getBrainkey()
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the brainKey from the authorities db table for the current user account and if it is not null it passes
|
||||
* the brainKey to a method to show it in a nice MaterialDialog
|
||||
|
|
|
@ -19,14 +19,15 @@
|
|||
android:layout_marginTop="@dimen/spacing_same_topic"
|
||||
android:src="@drawable/ic_lock"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:contentDescription="@string/title__re_enter_your_pin" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_same_topic"
|
||||
android:text="Enter your PIN"
|
||||
tools:text="Enter your PIN"
|
||||
android:textAppearance="@style/TextAppearance.Bitsy.Headline5"
|
||||
app:layout_constraintTop_toBottomOf="@id/ivLock" />
|
||||
|
||||
|
@ -35,7 +36,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Enter your BiTSy PIN to continue"
|
||||
tools:text="Enter your BiTSy PIN to continue"
|
||||
android:textAppearance="@style/TextAppearance.Bitsy.Body1"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvTitle"/>
|
||||
|
||||
|
|
|
@ -144,5 +144,12 @@
|
|||
<string name="text__pin">PIN</string>
|
||||
<string name="text__pattern">Patrón</string>
|
||||
<string name="text__none">Ninguno</string>
|
||||
<string name="title__re_enter_your_pin">Reingresa tu PIN</string>
|
||||
<string name="msg__enter_your_pin">Digita tu PIN de BiTSy para continuar</string>
|
||||
<string name="error__wrong_pin">PIN incorrecto</string>
|
||||
<string name="title__set_bitsy_screen_lock">Crea un bloqueo de seguridad para BiTSy</string>
|
||||
<string name="msg__set_bitsy_pin">Por seguridad, crea un PIN para BiTSy</string>
|
||||
<string name="msg__min_pin_length">El PIN debe tener al menos 6 dígitos</string>
|
||||
<string name="title__pins_dont_match">El PIN no concuerda</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -145,5 +145,12 @@
|
|||
<string name="text__pin">PIN</string>
|
||||
<string name="text__pattern">Pattern</string>
|
||||
<string name="text__none">None</string>
|
||||
<string name="title__re_enter_your_pin">Re-enter your PIN</string>
|
||||
<string name="msg__enter_your_pin">Enter your BiTSy PIN to continue</string>
|
||||
<string name="error__wrong_pin">Wrong PIN</string>
|
||||
<string name="title__set_bitsy_screen_lock">Set BiTSy screen lock</string>
|
||||
<string name="msg__set_bitsy_pin">For security, set BiTSy PIN</string>
|
||||
<string name="msg__min_pin_length">PIN must be at least 6 digits</string>
|
||||
<string name="title__pins_dont_match">PINs don\'t match</string>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue