- Update the MaterialDialogs library version.

- Add the functionality to the Settings BrainKey's View & Show button. It first fetches the brainkey from the authorities db table and then shows it in a custom MaterialDialog so that the user can view and copy it.
This commit is contained in:
Severiano Jaramillo 2018-12-13 16:01:26 -06:00
parent f45d9055c3
commit 8f0026c205
8 changed files with 112 additions and 4 deletions

View file

@ -59,7 +59,7 @@ dependencies {
implementation 'com.moldedbits.r2d2:r2d2:1.0.1'
implementation 'com.google.zxing:core:3.3.1'
implementation 'me.dm7.barcodescanner:zxing:1.9.8'
implementation 'com.afollestad.material-dialogs:core:2.0.0-rc1'
implementation 'com.afollestad.material-dialogs:core:2.0.0-rc3'
// Android Debug Database
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'

View file

@ -39,14 +39,19 @@ class MainActivity : ConnectedActivity() {
val host: NavHostFragment = supportFragmentManager
.findFragmentById(R.id.navHostFragment) as NavHostFragment? ?: return
// Set up Action Bar
// Set up Action Bar with Navigation's controller
val navController = host.navController
appBarConfiguration = AppBarConfiguration(navController.graph)
// Sets up the ActionBar with the navigation controller so that it automatically responds to clicks on toolbar
// menu items and shows the up navigation button on all fragments except home (Balances)
setupActionBarWithNavController(navController, appBarConfiguration)
mHandler = Handler()
// When this runnable finishes it first verifies if the auto close feature is enabled and if it is then it
// closes the app, if not then it just restarts the Handler (timer)
mRunnable = Runnable {
if (PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean(Constants.KEY_AUTO_CLOSE_ACTIVATED, false))
@ -57,11 +62,17 @@ class MainActivity : ConnectedActivity() {
startHandler()
}
/**
* Restarts the Handler (timer) each time there is user's interaction
*/
override fun onUserInteraction() {
super.onUserInteraction()
restartHandler()
}
/**
* Stops and then restarts the Handler
*/
private fun restartHandler() {
stopHandler()
startHandler()

View file

@ -12,6 +12,9 @@ interface AuthorityDao {
@Insert
fun insert(authority: Authority)
@Query("SELECT * FROM authorities WHERE user_id=:userId LIMIT 1")
fun get(userId: String): Single<Authority>
@Query("SELECT * FROM authorities")
fun getAll(): LiveData<List<Authority>>

View file

@ -1,17 +1,31 @@
package cy.agorise.bitsybitshareswallet.fragments
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context.CLIPBOARD_SERVICE
import android.os.Bundle
import android.preference.PreferenceManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository
import cy.agorise.bitsybitshareswallet.utils.Constants
import cy.agorise.bitsybitshareswallet.utils.CryptoUtils
import cy.agorise.graphenej.BrainKey
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.fragment_settings.*
class SettingsFragment : Fragment() {
private val TAG = this.javaClass.simpleName
private var mDisposables = CompositeDisposable()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
@ -28,8 +42,14 @@ class SettingsFragment : Fragment() {
initAutoCloseSwitch()
initNightModeSwitch()
btnViewBrainKey.setOnClickListener { getBrainkey(it) }
}
/**
* Fetches the relevant preference from the SharedPreferences and configures the corresponding switch accordingly,
* and adds a listener to the said switch to store the preference in case the user changes it.
*/
private fun initAutoCloseSwitch() {
val autoCloseOn = PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(Constants.KEY_AUTO_CLOSE_ACTIVATED, false)
@ -42,6 +62,11 @@ class SettingsFragment : Fragment() {
}
}
/**
* Fetches the relevant preference from the SharedPreferences and configures the corresponding switch accordingly,
* and adds a listener to the said switch to store the preference in case the user changes it. Also makes a call to
* recreate the activity and apply the selected theme.
*/
private fun initNightModeSwitch() {
val nightModeOn = PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(Constants.KEY_NIGHT_MODE_ACTIVATED, false)
@ -57,5 +82,55 @@ class SettingsFragment : Fragment() {
activity?.recreate()
}
}
/**
* 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
*/
private fun getBrainkey(view: View) {
val userId = PreferenceManager.getDefaultSharedPreferences(view.context)
.getString(Constants.KEY_CURRENT_ACCOUNT_ID, "") ?: ""
val authorityRepository = AuthorityRepository(view.context)
mDisposables.add(authorityRepository.get(userId)
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { authority ->
if (authority != null) {
val plainBrainKey = CryptoUtils.decrypt(view.context, authority.encryptedBrainKey)
val plainSequenceNumber = CryptoUtils.decrypt(view.context, authority.encryptedSequenceNumber)
val sequenceNumber = Integer.parseInt(plainSequenceNumber)
val brainKey = BrainKey(plainBrainKey, sequenceNumber)
showBrainKeyDialog(view, brainKey)
}
}
)
}
/**
* Shows the plain brainkey in a dialog so that the user can view and Copy it.
*/
private fun showBrainKeyDialog(view: View, brainKey: BrainKey) {
MaterialDialog(view.context).show {
title(text = "BrainKey")
message(text = brainKey.brainKey)
customView(R.layout.dialog_copy_brainkey)
cancelable(false)
positiveButton(android.R.string.copy) {
Toast.makeText(it.context, "Copied to clipboard", Toast.LENGTH_SHORT).show()
val clipboard = it.context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText("label", brainKey.brainKey)
clipboard.primaryClip = clip
it.dismiss()
}
}
}
override fun onDestroy() {
super.onDestroy()
if (!mDisposables.isDisposed) mDisposables.dispose()
}
}

View file

@ -122,7 +122,8 @@ class TransfersLoader(private var mContext: Context?): ServiceConnection {
Log.e(TAG, "AEADBadTagException. Class: " + e.javaClass + ", Msg: " + e.message)
}
})
}
)
mDisposables.add(RxBus.getBusInstance()
.asFlowable()
.observeOn(AndroidSchedulers.mainThread())
@ -145,7 +146,8 @@ class TransfersLoader(private var mContext: Context?): ServiceConnection {
responseMap.clear()
}
}
}))
})
)
} else {
// If there is no current user, we should not do anything
mState = State.CANCELLED

View file

@ -20,6 +20,10 @@ class AuthorityRepository internal constructor(context: Context) {
insertAsyncTask(mAuthorityDao).execute(authority)
}
fun get(userId: String): Single<Authority> {
return mAuthorityDao.get(userId)
}
fun getWIF(userId: String, authorityType: Int): Single<String> {
return mAuthorityDao.getWIF(userId, authorityType)
}

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/msg__brainkey_info"
android:textSize="13sp"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingStart="@dimen/activity_horizontal_margin"
android:paddingEnd="@dimen/activity_horizontal_margin"/>

View file

@ -66,6 +66,8 @@
<string name="msg__brainkey_description">BrainKey. Account recovery words that can be captured or copied, but not
edited.
</string>
<string name="msg__brainkey_info">Print this out, or write it down. Anyone with access to your recovery key will
have access to funds within this wallet.</string>
<string name="btn__view_and_copy"><![CDATA[View & Copy]]></string>
<string name="title__bugs_or_ideas">Bugs or Ideas?</string>
<string name="msg__bugs_or_ideas">Telegram chat: http://t.me/Agorise\nEmail: Agorise@protonmail.ch\nOpen Source: