- 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) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {

View file

@ -16,5 +16,5 @@ interface AssetDao {
fun insertAll(assets: List<Asset>)
@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 = "description") val description: 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.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
@ -17,21 +18,30 @@ import com.google.zxing.EncodeHintType
import com.google.zxing.MultiFormatWriter
import com.google.zxing.WriterException
import com.google.zxing.common.BitMatrix
import com.jakewharton.rxbinding2.widget.RxTextView
import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.utils.Constants
import cy.agorise.bitsybitshareswallet.viewmodels.AssetViewModel
import cy.agorise.bitsybitshareswallet.viewmodels.UserAccountViewModel
import cy.agorise.graphenej.*
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.fragment_receive_transaction.*
import java.util.*
import java.util.concurrent.TimeUnit
class ReceiveTransactionFragment : Fragment() {
private val TAG = this.javaClass.simpleName
private lateinit var mUserAccountViewModel: UserAccountViewModel
private lateinit var mAssetViewModel: AssetViewModel
/** Current user account */
private var mUserAccount: UserAccount? = null
private var mDisposables = CompositeDisposable()
private var mAsset: Asset? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_receive_transaction, container, false)
}
@ -48,16 +58,41 @@ class ReceiveTransactionFragment : Fragment() {
mUserAccountViewModel.getUserAccount(userId!!).observe(this,
Observer<cy.agorise.bitsybitshareswallet.database.entities.UserAccount>{ user ->
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() {
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 invoice = Invoice(mUserAccount!!.name, "", "#bitsy", inputCoinType, items, "", "")
val invoice = Invoice(mUserAccount!!.name, "", "#bitsy", mAsset!!.symbol, items, "", "")
Log.d(TAG, "invoice: " + invoice.toJsonString())
try {
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.jakewharton.rxbinding2.widget.RxTextView
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.repositories.AuthorityRepository
import cy.agorise.bitsybitshareswallet.utils.Constants
@ -75,7 +75,7 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
private lateinit var mBalanceDetailViewModel: BalanceDetailViewModel
private var mAssetsAdapter: AssetsAdapter? = null
private var mBalancesDetailsAdapter: BalancesDetailsAdapter? = null
private var selectedAssetSymbol = ""
@ -129,12 +129,12 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
mBalanceDetailViewModel.getAll().observe(this, Observer<List<BalanceDetail>> { balancesDetails ->
mBalancesDetails = balancesDetails
mAssetsAdapter = AssetsAdapter(context!!, android.R.layout.simple_spinner_item, mBalancesDetails!!)
spAsset.adapter = mAssetsAdapter
mBalancesDetailsAdapter = BalancesDetailsAdapter(context!!, android.R.layout.simple_spinner_item, mBalancesDetails!!)
spAsset.adapter = mBalancesDetailsAdapter
// Try to select the selectedAssetSymbol
for (i in 0 until mAssetsAdapter!!.count) {
if (mAssetsAdapter!!.getItem(i)!!.symbol == selectedAssetSymbol) {
for (i in 0 until mBalancesDetailsAdapter!!.count) {
if (mBalancesDetailsAdapter!!.getItem(i)!!.symbol == selectedAssetSymbol) {
spAsset.setSelection(i)
break
}
@ -145,7 +145,7 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
override fun onNothingSelected(parent: AdapterView<*>?) { }
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val balance = mAssetsAdapter!!.getItem(position)!!
val balance = mBalancesDetailsAdapter!!.getItem(position)!!
selectedAssetSymbol = balance.symbol
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!!)
mDisposables.add(authorityRepository!!.getWIF(userId!!, AuthorityType.ACTIVE.ordinal)
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { encryptedWIF ->
try {
wifKey = CryptoUtils.decrypt(context!!, encryptedWIF)
} catch (e: AEADBadTagException) {
Log.e(TAG, "AEADBadTagException. Class: " + e.javaClass + ", Msg: " + e.message)
}
mDisposables.add(
authorityRepository!!.getWIF(userId!!, AuthorityType.ACTIVE.ordinal)
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { encryptedWIF ->
try {
wifKey = CryptoUtils.decrypt(context!!, encryptedWIF)
} 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
mDisposables.add(RxTextView.textChanges(tietTo)
.debounce(500, TimeUnit.MILLISECONDS)
.map { it.toString().trim() }
.filter { it.length > 1 }
.subscribe {
val id = mNetworkService!!.sendMessage(GetAccountByName(it!!), GetAccountByName.REQUIRED_API)
responseMap[id] = RESPONSE_GET_ACCOUNT_BY_NAME
}
mDisposables.add(
RxTextView.textChanges(tietTo)
.debounce(500, TimeUnit.MILLISECONDS)
.map { it.toString().trim() }
.filter { it.length > 1 }
.subscribe {
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
mDisposables.add(RxTextView.textChanges(tietAmount)
.debounce(500, TimeUnit.MILLISECONDS)
.filter { it.isNotEmpty() }
.map { it.toString().trim().toDouble() }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { validateAmount(it!!) }
mDisposables.add(
RxTextView.textChanges(tietAmount)
.debounce(500, TimeUnit.MILLISECONDS)
.filter { it.isNotEmpty() }
.map { it.toString().trim().toDouble() }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { validateAmount(it!!) }
)
// Connect to the RxBus, which receives events from the NetworkService
mDisposables.add(RxBus.getBusInstance()
mDisposables.add(
RxBus.getBusInstance()
.asFlowable()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { handleIncomingMessage(it) }
@ -244,7 +249,7 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
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)
responseMap[id] = RESPONSE_GET_REQUIRED_FEES
@ -317,8 +322,8 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
tietTo.setText(invoice.to)
for (i in 0 until mAssetsAdapter!!.count) {
if (mAssetsAdapter!!.getItem(i)!!.symbol == invoice.currency.toUpperCase()) {
for (i in 0 until mBalancesDetailsAdapter!!.count) {
if (mBalancesDetailsAdapter!!.getItem(i)!!.symbol == invoice.currency.toUpperCase()) {
spAsset.setSelection(i)
break
}
@ -341,7 +346,7 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
}
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())
if (currentAmount < amount) {
@ -365,7 +370,7 @@ class SendTransactionFragment : Fragment(), ZXingScannerView.ResultHandler, Serv
private fun startSendTransferOperation() {
// Create TransferOperation
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 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.os.AsyncTask
import androidx.lifecycle.LiveData
import cy.agorise.bitsybitshareswallet.database.daos.AssetDao
import cy.agorise.bitsybitshareswallet.database.BitsyDatabase
import cy.agorise.bitsybitshareswallet.database.entities.Asset
@ -15,6 +16,10 @@ class AssetRepository internal constructor(application: Application) {
mAssetDao = db!!.assetDao()
}
fun getAll(): LiveData<List<Asset>> {
return mAssetDao.getAll()
}
fun insertAll(assets: List<Asset>) {
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()
}
}