Add functionality to ImportBrainkeyFragment's 'View Network Status' to show the nodes dialog. Most of it was copied fom the same dialog already implemented in the Settings screen.

This commit is contained in:
Severiano Jaramillo 2019-01-11 13:46:50 -06:00
parent dd619be8c8
commit 81531cc8b6
2 changed files with 113 additions and 2 deletions

View file

@ -1,6 +1,9 @@
package cy.agorise.bitsybitshareswallet.fragments package cy.agorise.bitsybitshareswallet.fragments
import android.content.ComponentName
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.os.IBinder
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -8,24 +11,34 @@ import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.navigation.Navigation import androidx.navigation.Navigation
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.list.customListAdapter
import com.afollestad.materialdialogs.list.listItemsSingleChoice import com.afollestad.materialdialogs.list.listItemsSingleChoice
import com.jakewharton.rxbinding3.widget.textChanges import com.jakewharton.rxbinding3.widget.textChanges
import cy.agorise.bitsybitshareswallet.BuildConfig
import cy.agorise.bitsybitshareswallet.R import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.adapters.FullNodesAdapter
import cy.agorise.bitsybitshareswallet.utils.Constants import cy.agorise.bitsybitshareswallet.utils.Constants
import cy.agorise.bitsybitshareswallet.utils.toast import cy.agorise.bitsybitshareswallet.utils.toast
import cy.agorise.graphenej.* import cy.agorise.graphenej.*
import cy.agorise.graphenej.api.ConnectionStatusUpdate import cy.agorise.graphenej.api.ConnectionStatusUpdate
import cy.agorise.graphenej.api.calls.GetAccounts import cy.agorise.graphenej.api.calls.GetAccounts
import cy.agorise.graphenej.api.calls.GetDynamicGlobalProperties
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.DynamicGlobalProperties
import cy.agorise.graphenej.models.JsonRpcResponse import cy.agorise.graphenej.models.JsonRpcResponse
import cy.agorise.graphenej.network.FullNode
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.fragment_import_brainkey.* import kotlinx.android.synthetic.main.fragment_import_brainkey.*
import org.bitcoinj.core.ECKey import org.bitcoinj.core.ECKey
import java.text.NumberFormat
import java.util.ArrayList import java.util.ArrayList
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class ImportBrainkeyFragment : BaseAccountFragment() { class ImportBrainkeyFragment : BaseAccountFragment() {
companion object { companion object {
private const val TAG = "ImportBrainkeyActivity" private const val TAG = "ImportBrainkeyActivity"
} }
@ -48,6 +61,15 @@ class ImportBrainkeyFragment : BaseAccountFragment() {
private var isPINConfirmationValid = false private var isPINConfirmationValid = false
private var isBrainKeyValid = false private var isBrainKeyValid = false
// Dialog displaying the list of nodes and their latencies
private var mNodesDialog: MaterialDialog? = null
/** Adapter that holds the FullNode list used in the Bitshares nodes modal */
private var mNodesAdapter: FullNodesAdapter? = null
/** Handler that will be used to make recurrent calls to get the latest BitShares block number*/
private val mHandler = Handler()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Remove up navigation icon from the toolbar // Remove up navigation icon from the toolbar
val toolbar: Toolbar? = activity?.findViewById(R.id.toolbar) val toolbar: Toolbar? = activity?.findViewById(R.id.toolbar)
@ -93,6 +115,32 @@ class ImportBrainkeyFragment : BaseAccountFragment() {
btnCreate.setOnClickListener ( btnCreate.setOnClickListener (
Navigation.createNavigateOnClickListener(R.id.create_account_action) Navigation.createNavigateOnClickListener(R.id.create_account_action)
) )
tvNetworkStatus.setOnClickListener { v ->
if (mNetworkService != null) {
// PublishSubject used to announce full node latencies updates
val fullNodePublishSubject = mNetworkService!!.nodeLatencyObservable
fullNodePublishSubject?.observeOn(AndroidSchedulers.mainThread())?.subscribe(nodeLatencyObserver)
val fullNodes = mNetworkService!!.nodes
mNodesAdapter = FullNodesAdapter(v.context)
mNodesAdapter?.add(fullNodes)
mNodesDialog = MaterialDialog(v.context)
.title(text = String.format("%s v%s", getString(R.string.app_name), BuildConfig.VERSION_NAME))
.message(text = getString(R.string.title__bitshares_nodes_dialog, "-------"))
.customListAdapter(mNodesAdapter as FullNodesAdapter)
.negativeButton(android.R.string.ok) {
mHandler.removeCallbacks(mRequestDynamicGlobalPropertiesTask)
}
mNodesDialog?.show()
// Registering a recurrent task used to poll for dynamic global properties requests
mHandler.post(mRequestDynamicGlobalPropertiesTask)
}
}
} }
private fun validatePIN() { private fun validatePIN() {
@ -196,6 +244,12 @@ class ImportBrainkeyFragment : BaseAccountFragment() {
handleBrainKeyAccountReferences(response.result) handleBrainKeyAccountReferences(response.result)
} else if (response.id == getAccountsRequestId) { } else if (response.id == getAccountsRequestId) {
handleAccountProperties(response.result) handleAccountProperties(response.result)
} else if (response.result is DynamicGlobalProperties) {
val dynamicGlobalProperties = response.result as DynamicGlobalProperties
if (mNodesDialog != null && mNodesDialog?.isShowing == true) {
val blockNumber = NumberFormat.getInstance().format(dynamicGlobalProperties.head_block_number)
mNodesDialog?.message(text = getString(R.string.title__bitshares_nodes_dialog, blockNumber))
}
} }
} }
@ -281,4 +335,58 @@ class ImportBrainkeyFragment : BaseAccountFragment() {
} }
} }
} }
/**
* Observer used to be notified about node latency measurement updates.
*/
private val nodeLatencyObserver = object : Observer<FullNode> {
override fun onSubscribe(d: Disposable) {
mDisposables.add(d)
}
override fun onNext(fullNode: FullNode) {
if (!fullNode.isRemoved)
mNodesAdapter?.add(fullNode)
else
mNodesAdapter?.remove(fullNode)
}
override fun onError(e: Throwable) {
Log.e(TAG, "nodeLatencyObserver.onError.Msg: " + e.message)
}
override fun onComplete() {}
}
/**
* Task used to obtain frequent updates on the global dynamic properties object
*/
private val mRequestDynamicGlobalPropertiesTask = object : Runnable {
override fun run() {
if (mNetworkService != null) {
if (mNetworkService?.isConnected == true) {
mNetworkService?.sendMessage(GetDynamicGlobalProperties(), GetDynamicGlobalProperties.REQUIRED_API)
} else {
Log.d(TAG, "NetworkService exists but is not connected")
}
} else {
Log.d(TAG, "NetworkService reference is null")
}
mHandler.postDelayed(this, Constants.BLOCK_PERIOD)
}
}
override fun onServiceDisconnected(name: ComponentName?) {
super.onServiceDisconnected(name)
tvNetworkStatus.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null,
resources.getDrawable(R.drawable.ic_disconnected, null), null)
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
super.onServiceConnected(name, service)
tvNetworkStatus.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null,
resources.getDrawable(R.drawable.ic_connected, null), null)
}
} }

View file

@ -35,7 +35,10 @@ import kotlinx.android.synthetic.main.fragment_settings.*
import java.text.NumberFormat import java.text.NumberFormat
class SettingsFragment : Fragment(), ServiceConnection { class SettingsFragment : Fragment(), ServiceConnection {
private val TAG = this.javaClass.simpleName
companion object {
private const val TAG = "SettingsFragment"
}
private var mDisposables = CompositeDisposable() private var mDisposables = CompositeDisposable()
@ -77,7 +80,7 @@ class SettingsFragment : Fragment(), ServiceConnection {
val fullNodes = mNetworkService!!.nodes val fullNodes = mNetworkService!!.nodes
nodesAdapter = FullNodesAdapter(v.context) nodesAdapter = FullNodesAdapter(v.context)
nodesAdapter!!.add(fullNodes) nodesAdapter?.add(fullNodes)
mNodesDialog = MaterialDialog(v.context) mNodesDialog = MaterialDialog(v.context)
.title(text = String.format("%s v%s", getString(R.string.app_name), BuildConfig.VERSION_NAME)) .title(text = String.format("%s v%s", getString(R.string.app_name), BuildConfig.VERSION_NAME))