From 8f0026c2056d1436f1e1901a93566d488c981db7 Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Thu, 13 Dec 2018 16:01:26 -0600 Subject: [PATCH] - 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. --- app/build.gradle | 2 +- .../activities/MainActivity.kt | 13 +++- .../database/daos/AuthorityDao.kt | 3 + .../fragments/SettingsFragment.kt | 75 +++++++++++++++++++ .../processors/TransfersLoader.kt | 6 +- .../repositories/AuthorityRepository.kt | 4 + .../main/res/layout/dialog_copy_brainkey.xml | 11 +++ app/src/main/res/values/strings.xml | 2 + 8 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 app/src/main/res/layout/dialog_copy_brainkey.xml diff --git a/app/build.gradle b/app/build.gradle index 555ae82..8e116b7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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' diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/activities/MainActivity.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/activities/MainActivity.kt index 92a619a..6cebcf7 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/activities/MainActivity.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/activities/MainActivity.kt @@ -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() diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/database/daos/AuthorityDao.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/database/daos/AuthorityDao.kt index 5956e15..fecff8c 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/database/daos/AuthorityDao.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/database/daos/AuthorityDao.kt @@ -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 + @Query("SELECT * FROM authorities") fun getAll(): LiveData> diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/fragments/SettingsFragment.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/fragments/SettingsFragment.kt index 42728f4..94ab336 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/fragments/SettingsFragment.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/fragments/SettingsFragment.kt @@ -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() + } } diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/processors/TransfersLoader.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/processors/TransfersLoader.kt index 3cca418..13255b7 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/processors/TransfersLoader.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/processors/TransfersLoader.kt @@ -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 diff --git a/app/src/main/java/cy/agorise/bitsybitshareswallet/repositories/AuthorityRepository.kt b/app/src/main/java/cy/agorise/bitsybitshareswallet/repositories/AuthorityRepository.kt index 46ad1f3..e241170 100644 --- a/app/src/main/java/cy/agorise/bitsybitshareswallet/repositories/AuthorityRepository.kt +++ b/app/src/main/java/cy/agorise/bitsybitshareswallet/repositories/AuthorityRepository.kt @@ -20,6 +20,10 @@ class AuthorityRepository internal constructor(context: Context) { insertAsyncTask(mAuthorityDao).execute(authority) } + fun get(userId: String): Single { + return mAuthorityDao.get(userId) + } + fun getWIF(userId: String, authorityType: Int): Single { return mAuthorityDao.getWIF(userId, authorityType) } diff --git a/app/src/main/res/layout/dialog_copy_brainkey.xml b/app/src/main/res/layout/dialog_copy_brainkey.xml new file mode 100644 index 0000000..f4d31a9 --- /dev/null +++ b/app/src/main/res/layout/dialog_copy_brainkey.xml @@ -0,0 +1,11 @@ + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 273049e..469970f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -66,6 +66,8 @@ BrainKey. Account recovery words that can be captured or copied, but not edited. + Print this out, or write it down. Anyone with access to your recovery key will + have access to funds within this wallet. Bugs or Ideas? Telegram chat: http://t.me/Agorise\nEmail: Agorise@protonmail.ch\nOpen Source: