Improve ImportBrainkeyActivity by automatically showing errors if the PIN is not long enough, the PIN Confirmation does not match or if the brainkey does not have the correct format as the user types but with a small debunce to avoid showing errors while the user is typing. Once the three fields are correct then the Import button is enabled.
This commit is contained in:
parent
bada77f224
commit
2dc0deb23f
2 changed files with 83 additions and 27 deletions
|
@ -4,10 +4,10 @@ import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.inputmethod.EditorInfo
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.list.listItemsSingleChoice
|
import com.afollestad.materialdialogs.list.listItemsSingleChoice
|
||||||
|
import com.jakewharton.rxbinding2.widget.RxTextView
|
||||||
import cy.agorise.bitsybitshareswallet.R
|
import cy.agorise.bitsybitshareswallet.R
|
||||||
import cy.agorise.bitsybitshareswallet.database.entities.Authority
|
import cy.agorise.bitsybitshareswallet.database.entities.Authority
|
||||||
import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository
|
import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository
|
||||||
|
@ -20,9 +20,12 @@ import cy.agorise.graphenej.api.calls.GetAccounts
|
||||||
import cy.agorise.graphenej.api.calls.GetKeyReferences
|
import cy.agorise.graphenej.api.calls.GetKeyReferences
|
||||||
import cy.agorise.graphenej.models.AccountProperties
|
import cy.agorise.graphenej.models.AccountProperties
|
||||||
import cy.agorise.graphenej.models.JsonRpcResponse
|
import cy.agorise.graphenej.models.JsonRpcResponse
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import kotlinx.android.synthetic.main.activity_import_brainkey.*
|
import kotlinx.android.synthetic.main.activity_import_brainkey.*
|
||||||
import org.bitcoinj.core.ECKey
|
import org.bitcoinj.core.ECKey
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
// TODO Add method to load the 20? most important assets
|
// TODO Add method to load the 20? most important assets
|
||||||
// TODO add progress bar or something while the user waits for the import response from the node
|
// TODO add progress bar or something while the user waits for the import response from the node
|
||||||
|
@ -51,41 +54,90 @@ class ImportBrainkeyActivity : ConnectedActivity() {
|
||||||
private var keyReferencesRequestId: Long = 0
|
private var keyReferencesRequestId: Long = 0
|
||||||
private var getAccountsRequestId: Long = 0
|
private var getAccountsRequestId: Long = 0
|
||||||
|
|
||||||
|
private var mDisposables = CompositeDisposable()
|
||||||
|
|
||||||
|
private var isPINValid = false
|
||||||
|
private var isPINConfirmationValid = false
|
||||||
|
private var isBrainKeyValid = false
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_import_brainkey)
|
setContentView(R.layout.activity_import_brainkey)
|
||||||
|
|
||||||
// Custom event to activate import account from the keyboard
|
// Use RxJava Debounce to update the PIN error only after the user stops writing for > 500 ms
|
||||||
tietBrainKey.setOnEditorActionListener { _, actionId, _ ->
|
mDisposables.add(
|
||||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
RxTextView.textChanges(tietPin)
|
||||||
importAccount()
|
.skipInitialValue()
|
||||||
true
|
.debounce(500, TimeUnit.MILLISECONDS)
|
||||||
} else
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
false
|
.subscribe { validatePIN() }
|
||||||
|
)
|
||||||
|
|
||||||
|
// Use RxJava Debounce to update the PIN Confirmation error only after the user stops writing for > 500 ms
|
||||||
|
mDisposables.add(
|
||||||
|
RxTextView.textChanges(tietPinConfirmation)
|
||||||
|
.skipInitialValue()
|
||||||
|
.debounce(500, TimeUnit.MILLISECONDS)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe { validatePINConfirmation() }
|
||||||
|
)
|
||||||
|
|
||||||
|
// Use RxJava Debounce to update the BrainKey error only after the user stops writing for > 500 ms
|
||||||
|
mDisposables.add(
|
||||||
|
RxTextView.textChanges(tietBrainKey)
|
||||||
|
.skipInitialValue()
|
||||||
|
.debounce(500, TimeUnit.MILLISECONDS)
|
||||||
|
.map { it.toString().trim() }
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe { validateBrainKey(it) }
|
||||||
|
)
|
||||||
|
|
||||||
|
btnImport.isEnabled = false
|
||||||
|
btnImport.setOnClickListener { verifyBrainKey(false) }
|
||||||
}
|
}
|
||||||
|
|
||||||
btnImport.setOnClickListener { importAccount() }
|
private fun validatePIN() {
|
||||||
}
|
val pin = tietPin.text.toString()
|
||||||
|
|
||||||
private fun importAccount() {
|
if (pin.length < Constants.MIN_PIN_LENGTH) {
|
||||||
tilPin.isErrorEnabled = false
|
|
||||||
tilPinConfirmation.isErrorEnabled = false
|
|
||||||
tilBrainKey.isErrorEnabled = false
|
|
||||||
|
|
||||||
if (tietPin.text!!.length < Constants.MIN_PIN_LENGTH)
|
|
||||||
tilPin.error = getString(R.string.error__pin_too_short)
|
tilPin.error = getString(R.string.error__pin_too_short)
|
||||||
else if (tietPin.text.toString() != tietPinConfirmation.text.toString())
|
isPINValid = false
|
||||||
tilPinConfirmation.error = getString(R.string.error__pin_mismatch)
|
} else {
|
||||||
else if (tietBrainKey.text!!.isEmpty() || !tietBrainKey.text.toString().contains(" "))
|
tilPin.isErrorEnabled = false
|
||||||
tilBrainKey.error = getString(R.string.error__enter_correct_brainkey)
|
isPINValid = true
|
||||||
else {
|
|
||||||
val brainKey = tietBrainKey.text.toString()
|
|
||||||
if (brainKey.split(" ").size in 12..16)
|
|
||||||
verifyBrainKey(false)
|
|
||||||
else
|
|
||||||
tilBrainKey.error = getString(R.string.error__enter_correct_brainkey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validatePINConfirmation()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validatePINConfirmation() {
|
||||||
|
val pinConfirmation = tietPinConfirmation.text.toString()
|
||||||
|
|
||||||
|
if (pinConfirmation != tietPin.text.toString()) {
|
||||||
|
tilPinConfirmation.error = getString(R.string.error__pin_mismatch)
|
||||||
|
isPINConfirmationValid = false
|
||||||
|
} else {
|
||||||
|
tilPinConfirmation.isErrorEnabled = false
|
||||||
|
isPINConfirmationValid = true
|
||||||
|
}
|
||||||
|
|
||||||
|
enableDisableImportButton()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateBrainKey(brainKey: String) {
|
||||||
|
if (brainKey.isEmpty() || !brainKey.contains(" ") || brainKey.split(" ").size !in 12..16) {
|
||||||
|
tilBrainKey.error = getString(R.string.error__enter_correct_brainkey)
|
||||||
|
isBrainKeyValid = false
|
||||||
|
} else {
|
||||||
|
tilBrainKey.isErrorEnabled = false
|
||||||
|
isBrainKeyValid = true
|
||||||
|
}
|
||||||
|
|
||||||
|
enableDisableImportButton()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun enableDisableImportButton() {
|
||||||
|
btnImport.isEnabled = (isPINValid && isPINConfirmationValid && isBrainKeyValid)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -296,4 +348,10 @@ class ImportBrainkeyActivity : ConnectedActivity() {
|
||||||
val authorityRepository = AuthorityRepository(this)
|
val authorityRepository = AuthorityRepository(this)
|
||||||
authorityRepository.insert(authority)
|
authorityRepository.insert(authority)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
|
||||||
|
if (!mDisposables.isDisposed) mDisposables.dispose()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -5,7 +5,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:focusableInTouchMode="true"
|
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context=".activities.ImportBrainkeyActivity">
|
tools:context=".activities.ImportBrainkeyActivity">
|
||||||
|
|
||||||
|
@ -78,7 +77,6 @@
|
||||||
android:layout_marginTop="@dimen/spacing_different_topic"
|
android:layout_marginTop="@dimen/spacing_different_topic"
|
||||||
android:layout_marginStart="@dimen/activity_horizontal_margin"
|
android:layout_marginStart="@dimen/activity_horizontal_margin"
|
||||||
android:layout_marginEnd="@dimen/activity_horizontal_margin"
|
android:layout_marginEnd="@dimen/activity_horizontal_margin"
|
||||||
android:backgroundTint="@color/colorPrimary"
|
|
||||||
android:text="@string/button__import"/>
|
android:text="@string/button__import"/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
|
Loading…
Reference in a new issue