- 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:
parent
b9a765e682
commit
28561d55f1
7 changed files with 108 additions and 44 deletions
|
@ -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 {
|
|
@ -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>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue