- Modified the Asset entity model by adding a method 'toString()', so that it can be used in the adapter for the ReceiveTransactionFragment's Asset AutoCompleteTextView.

- Created AssetViewModel to obtain the the elements from the assetd db table using the AssetRepository and serving the obtained assets to the ReceiveTransactionFragment.
- Fire an event to update the QR code when the user selects an asset from the AutoCompleteTextView.
This commit is contained in:
Severiano Jaramillo 2018-12-07 13:50:31 -06:00
parent b9a765e682
commit 28561d55f1
7 changed files with 108 additions and 44 deletions

View file

@ -10,7 +10,7 @@ import cy.agorise.bitsybitshareswallet.database.joins.BalanceDetail
class AssetsAdapter(context: Context, resource: Int, data: List<BalanceDetail>) : class BalancesDetailsAdapter(context: Context, resource: Int, data: List<BalanceDetail>) :
ArrayAdapter<BalanceDetail>(context, resource, data) { ArrayAdapter<BalanceDetail>(context, resource, data) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {

View file

@ -16,5 +16,5 @@ interface AssetDao {
fun insertAll(assets: List<Asset>) fun insertAll(assets: List<Asset>)
@Query("SELECT * FROM assets") @Query("SELECT * FROM assets")
fun getAllAssets(): LiveData<List<Asset>> fun getAll(): LiveData<List<Asset>>
} }

View file

@ -12,4 +12,8 @@ data class Asset(
@ColumnInfo(name = "precision") val precision: Int, @ColumnInfo(name = "precision") val precision: Int,
@ColumnInfo(name = "description") val description: String, @ColumnInfo(name = "description") val description: String,
@ColumnInfo(name = "bit_asset_id") val bitAssetId: String @ColumnInfo(name = "bit_asset_id") val bitAssetId: String
) ) {
override fun toString(): String {
return symbol
}
}

View file

@ -8,6 +8,7 @@ import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders import androidx.lifecycle.ViewModelProviders
@ -17,21 +18,30 @@ import com.google.zxing.EncodeHintType
import com.google.zxing.MultiFormatWriter import com.google.zxing.MultiFormatWriter
import com.google.zxing.WriterException import com.google.zxing.WriterException
import com.google.zxing.common.BitMatrix import com.google.zxing.common.BitMatrix
import com.jakewharton.rxbinding2.widget.RxTextView
import cy.agorise.bitsybitshareswallet.R import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.utils.Constants import cy.agorise.bitsybitshareswallet.utils.Constants
import cy.agorise.bitsybitshareswallet.viewmodels.AssetViewModel
import cy.agorise.bitsybitshareswallet.viewmodels.UserAccountViewModel import cy.agorise.bitsybitshareswallet.viewmodels.UserAccountViewModel
import cy.agorise.graphenej.* import cy.agorise.graphenej.*
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.fragment_receive_transaction.* import kotlinx.android.synthetic.main.fragment_receive_transaction.*
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit
class ReceiveTransactionFragment : Fragment() { class ReceiveTransactionFragment : Fragment() {
private val TAG = this.javaClass.simpleName private val TAG = this.javaClass.simpleName
private lateinit var mUserAccountViewModel: UserAccountViewModel private lateinit var mUserAccountViewModel: UserAccountViewModel
private lateinit var mAssetViewModel: AssetViewModel
/** Current user account */ /** Current user account */
private var mUserAccount: UserAccount? = null private var mUserAccount: UserAccount? = null
private var mDisposables = CompositeDisposable()
private var mAsset: Asset? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_receive_transaction, container, false) return inflater.inflate(R.layout.fragment_receive_transaction, container, false)
} }
@ -48,16 +58,41 @@ class ReceiveTransactionFragment : Fragment() {
mUserAccountViewModel.getUserAccount(userId!!).observe(this, mUserAccountViewModel.getUserAccount(userId!!).observe(this,
Observer<cy.agorise.bitsybitshareswallet.database.entities.UserAccount>{ user -> Observer<cy.agorise.bitsybitshareswallet.database.entities.UserAccount>{ user ->
mUserAccount = UserAccount(user.id, user.name) mUserAccount = UserAccount(user.id, user.name)
updateQR()
}) })
mAssetViewModel = ViewModelProviders.of(this).get(AssetViewModel::class.java)
mAssetViewModel.getAll().observe(this,
Observer<List<cy.agorise.bitsybitshareswallet.database.entities.Asset>> { assets ->
val adapter = ArrayAdapter<cy.agorise.bitsybitshareswallet.database.entities.Asset>(context!!,
android.R.layout.simple_dropdown_item_1line, assets)
actvAsset.setAdapter(adapter)
})
actvAsset.setOnItemClickListener { parent, _, position, _ ->
val asset = parent.adapter.getItem(position) as cy.agorise.bitsybitshareswallet.database.entities.Asset
mAsset = Asset(asset.id, asset.symbol, asset.precision)
updateQR()
}
// Use RxJava Debounce to avoid making calls to the NetworkService on every text change event
// mDisposables.add(
// RxTextView.textChanges(tietAmount)
// .debounce(500, TimeUnit.MILLISECONDS)
// .map { it.toString().trim() }
// .filter { it.length > 1 }
// .subscribe {
//
// }
// )
} }
private fun updateQR() { private fun updateQR() {
val inputCoinType = "bts" val amount: Long = 10
val total = Util.fromBase(AssetAmount(UnsignedLong.valueOf(10), Asset("1.3.0", "bts", 5))) val total = Util.fromBase(AssetAmount(UnsignedLong.valueOf(amount), mAsset!!))
val items = arrayOf(LineItem("transfer", 1, total)) val items = arrayOf(LineItem("transfer", 1, total))
val invoice = Invoice(mUserAccount!!.name, "", "#bitsy", inputCoinType, items, "", "") val invoice = Invoice(mUserAccount!!.name, "", "#bitsy", mAsset!!.symbol, items, "", "")
Log.d(TAG, "invoice: " + invoice.toJsonString()) Log.d(TAG, "invoice: " + invoice.toJsonString())
try { try {
val bitmap = encodeAsBitmap(Invoice.toQrCode(invoice), "#139657") // PalmPay green val bitmap = encodeAsBitmap(Invoice.toQrCode(invoice), "#139657") // PalmPay green

View file

@ -24,7 +24,7 @@ import com.google.zxing.BarcodeFormat
import com.google.zxing.Result import com.google.zxing.Result
import com.jakewharton.rxbinding2.widget.RxTextView import com.jakewharton.rxbinding2.widget.RxTextView
import cy.agorise.bitsybitshareswallet.R import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.adapters.AssetsAdapter import cy.agorise.bitsybitshareswallet.adapters.BalancesDetailsAdapter
import cy.agorise.bitsybitshareswallet.database.joins.BalanceDetail import cy.agorise.bitsybitshareswallet.database.joins.BalanceDetail
import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository
import cy.agorise.bitsybitshareswallet.utils.Constants import cy.agorise.bitsybitshareswallet.utils.Constants
@ -75,7 +75,7 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
private lateinit var mBalanceDetailViewModel: BalanceDetailViewModel private lateinit var mBalanceDetailViewModel: BalanceDetailViewModel
private var mAssetsAdapter: AssetsAdapter? = null private var mBalancesDetailsAdapter: BalancesDetailsAdapter? = null
private var selectedAssetSymbol = "" private var selectedAssetSymbol = ""
@ -129,12 +129,12 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
mBalanceDetailViewModel.getAll().observe(this, Observer<List<BalanceDetail>> { balancesDetails -> mBalanceDetailViewModel.getAll().observe(this, Observer<List<BalanceDetail>> { balancesDetails ->
mBalancesDetails = balancesDetails mBalancesDetails = balancesDetails
mAssetsAdapter = AssetsAdapter(context!!, android.R.layout.simple_spinner_item, mBalancesDetails!!) mBalancesDetailsAdapter = BalancesDetailsAdapter(context!!, android.R.layout.simple_spinner_item, mBalancesDetails!!)
spAsset.adapter = mAssetsAdapter spAsset.adapter = mBalancesDetailsAdapter
// Try to select the selectedAssetSymbol // Try to select the selectedAssetSymbol
for (i in 0 until mAssetsAdapter!!.count) { for (i in 0 until mBalancesDetailsAdapter!!.count) {
if (mAssetsAdapter!!.getItem(i)!!.symbol == selectedAssetSymbol) { if (mBalancesDetailsAdapter!!.getItem(i)!!.symbol == selectedAssetSymbol) {
spAsset.setSelection(i) spAsset.setSelection(i)
break break
} }
@ -145,7 +145,7 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
override fun onNothingSelected(parent: AdapterView<*>?) { } override fun onNothingSelected(parent: AdapterView<*>?) { }
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val balance = mAssetsAdapter!!.getItem(position)!! val balance = mBalancesDetailsAdapter!!.getItem(position)!!
selectedAssetSymbol = balance.symbol selectedAssetSymbol = balance.symbol
val amount = balance.amount.toDouble() / Math.pow(10.0, balance.precision.toDouble()) val amount = balance.amount.toDouble() / Math.pow(10.0, balance.precision.toDouble())
@ -160,40 +160,45 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
authorityRepository = AuthorityRepository(context!!) authorityRepository = AuthorityRepository(context!!)
mDisposables.add(authorityRepository!!.getWIF(userId!!, AuthorityType.ACTIVE.ordinal) mDisposables.add(
.subscribeOn(Schedulers.computation()) authorityRepository!!.getWIF(userId!!, AuthorityType.ACTIVE.ordinal)
.observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.computation())
.subscribe { encryptedWIF -> .observeOn(AndroidSchedulers.mainThread())
try { .subscribe { encryptedWIF ->
wifKey = CryptoUtils.decrypt(context!!, encryptedWIF) try {
} catch (e: AEADBadTagException) { wifKey = CryptoUtils.decrypt(context!!, encryptedWIF)
Log.e(TAG, "AEADBadTagException. Class: " + e.javaClass + ", Msg: " + e.message) } catch (e: AEADBadTagException) {
} Log.e(TAG, "AEADBadTagException. Class: " + e.javaClass + ", Msg: " + e.message)
}
}) }
)
// Use RxJava Debounce to avoid making calls to the NetworkService on every text change event // Use RxJava Debounce to avoid making calls to the NetworkService on every text change event
mDisposables.add(RxTextView.textChanges(tietTo) mDisposables.add(
.debounce(500, TimeUnit.MILLISECONDS) RxTextView.textChanges(tietTo)
.map { it.toString().trim() } .debounce(500, TimeUnit.MILLISECONDS)
.filter { it.length > 1 } .map { it.toString().trim() }
.subscribe { .filter { it.length > 1 }
val id = mNetworkService!!.sendMessage(GetAccountByName(it!!), GetAccountByName.REQUIRED_API) .subscribe {
responseMap[id] = RESPONSE_GET_ACCOUNT_BY_NAME val id = mNetworkService!!.sendMessage(GetAccountByName(it!!), GetAccountByName.REQUIRED_API)
} responseMap[id] = RESPONSE_GET_ACCOUNT_BY_NAME
}
) )
// Use RxJava Debounce to update the Amount error only after the user stops writing for > 500 ms // Use RxJava Debounce to update the Amount error only after the user stops writing for > 500 ms
mDisposables.add(RxTextView.textChanges(tietAmount) mDisposables.add(
.debounce(500, TimeUnit.MILLISECONDS) RxTextView.textChanges(tietAmount)
.filter { it.isNotEmpty() } .debounce(500, TimeUnit.MILLISECONDS)
.map { it.toString().trim().toDouble() } .filter { it.isNotEmpty() }
.observeOn(AndroidSchedulers.mainThread()) .map { it.toString().trim().toDouble() }
.subscribe { validateAmount(it!!) } .observeOn(AndroidSchedulers.mainThread())
.subscribe { validateAmount(it!!) }
) )
// Connect to the RxBus, which receives events from the NetworkService // Connect to the RxBus, which receives events from the NetworkService
mDisposables.add(RxBus.getBusInstance() mDisposables.add(
RxBus.getBusInstance()
.asFlowable() .asFlowable()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { handleIncomingMessage(it) } .subscribe { handleIncomingMessage(it) }
@ -244,7 +249,7 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
transaction!!.blockData = BlockData(headBlockNumber, headBlockId, expirationTime) transaction!!.blockData = BlockData(headBlockNumber, headBlockId, expirationTime)
val asset = Asset(mAssetsAdapter!!.getItem(spAsset.selectedItemPosition)!!.id) val asset = Asset(mBalancesDetailsAdapter!!.getItem(spAsset.selectedItemPosition)!!.id)
val id = mNetworkService!!.sendMessage(GetRequiredFees(transaction!!, asset), GetRequiredFees.REQUIRED_API) val id = mNetworkService!!.sendMessage(GetRequiredFees(transaction!!, asset), GetRequiredFees.REQUIRED_API)
responseMap[id] = RESPONSE_GET_REQUIRED_FEES responseMap[id] = RESPONSE_GET_REQUIRED_FEES
@ -317,8 +322,8 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
tietTo.setText(invoice.to) tietTo.setText(invoice.to)
for (i in 0 until mAssetsAdapter!!.count) { for (i in 0 until mBalancesDetailsAdapter!!.count) {
if (mAssetsAdapter!!.getItem(i)!!.symbol == invoice.currency.toUpperCase()) { if (mBalancesDetailsAdapter!!.getItem(i)!!.symbol == invoice.currency.toUpperCase()) {
spAsset.setSelection(i) spAsset.setSelection(i)
break break
} }
@ -341,7 +346,7 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
} }
private fun validateAmount(amount: Double) { private fun validateAmount(amount: Double) {
val balance = mAssetsAdapter!!.getItem(spAsset.selectedItemPosition)!! val balance = mBalancesDetailsAdapter!!.getItem(spAsset.selectedItemPosition)!!
val currentAmount = balance.amount.toDouble() / Math.pow(10.0, balance.precision.toDouble()) val currentAmount = balance.amount.toDouble() / Math.pow(10.0, balance.precision.toDouble())
if (currentAmount < amount) { if (currentAmount < amount) {
@ -365,7 +370,7 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
private fun startSendTransferOperation() { private fun startSendTransferOperation() {
// Create TransferOperation // Create TransferOperation
if (mNetworkService!!.isConnected) { if (mNetworkService!!.isConnected) {
val balance = mAssetsAdapter!!.getItem(spAsset.selectedItemPosition)!! val balance = mBalancesDetailsAdapter!!.getItem(spAsset.selectedItemPosition)!!
val amount = (tietAmount.text.toString().toDouble() * Math.pow(10.0, balance.precision.toDouble())).toLong() val amount = (tietAmount.text.toString().toDouble() * Math.pow(10.0, balance.precision.toDouble())).toLong()
val transferAmount = AssetAmount(UnsignedLong.valueOf(amount), Asset(balance.id)) val transferAmount = AssetAmount(UnsignedLong.valueOf(amount), Asset(balance.id))

View file

@ -2,6 +2,7 @@ package cy.agorise.bitsybitshareswallet.repositories
import android.app.Application import android.app.Application
import android.os.AsyncTask import android.os.AsyncTask
import androidx.lifecycle.LiveData
import cy.agorise.bitsybitshareswallet.database.daos.AssetDao import cy.agorise.bitsybitshareswallet.database.daos.AssetDao
import cy.agorise.bitsybitshareswallet.database.BitsyDatabase import cy.agorise.bitsybitshareswallet.database.BitsyDatabase
import cy.agorise.bitsybitshareswallet.database.entities.Asset import cy.agorise.bitsybitshareswallet.database.entities.Asset
@ -15,6 +16,10 @@ class AssetRepository internal constructor(application: Application) {
mAssetDao = db!!.assetDao() mAssetDao = db!!.assetDao()
} }
fun getAll(): LiveData<List<Asset>> {
return mAssetDao.getAll()
}
fun insertAll(assets: List<Asset>) { fun insertAll(assets: List<Asset>) {
insertAllAsyncTask(mAssetDao).execute(assets) insertAllAsyncTask(mAssetDao).execute(assets)
} }

View file

@ -0,0 +1,15 @@
package cy.agorise.bitsybitshareswallet.viewmodels
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import cy.agorise.bitsybitshareswallet.database.entities.Asset
import cy.agorise.bitsybitshareswallet.repositories.AssetRepository
class AssetViewModel(application: Application) : AndroidViewModel(application) {
private var mRepository = AssetRepository(application)
internal fun getAll(): LiveData<List<Asset>> {
return mRepository.getAll()
}
}