From e16308df9621e1129c871012b2bfd8fe307b05ac Mon Sep 17 00:00:00 2001 From: dreacot Date: Thu, 8 Apr 2021 22:21:10 +0100 Subject: [PATCH] add usd equivalent balance to overview page --- .../main/java/com/dcrandroid/HomeActivity.kt | 14 ++++ .../dialog/send/AmountInputHelper.kt | 59 ++++++++------- .../dialog/send/ConfirmTransaction.kt | 7 +- .../com/dcrandroid/dialog/send/SendDialog.kt | 5 +- .../com/dcrandroid/fragments/BaseFragment.kt | 7 ++ .../dcrandroid/fragments/OverviewFragment.kt | 71 +++++++++++++++++-- .../java/com/dcrandroid/util/CurrencyUtil.kt | 40 +++++++++++ .../res/drawable/light_grey_border_8dp.xml | 6 ++ app/src/main/res/layout/activity_tabs.xml | 19 ++++- app/src/main/res/layout/fragment_overview.xml | 15 ++-- app/src/main/res/values/strings.xml | 5 +- 11 files changed, 197 insertions(+), 51 deletions(-) create mode 100644 app/src/main/java/com/dcrandroid/util/CurrencyUtil.kt create mode 100644 app/src/main/res/drawable/light_grey_border_8dp.xml diff --git a/app/src/main/java/com/dcrandroid/HomeActivity.kt b/app/src/main/java/com/dcrandroid/HomeActivity.kt index 2f69479ca..4e39f1c3f 100644 --- a/app/src/main/java/com/dcrandroid/HomeActivity.kt +++ b/app/src/main/java/com/dcrandroid/HomeActivity.kt @@ -294,6 +294,20 @@ class HomeActivity : BaseActivity(), SyncProgressListener, TxAndBlockNotificatio } } + fun setToolbarSubTitle(title: CharSequence, showShadow: Boolean) { + if (title == "") { + toolbar_subtitle.visibility = View.GONE + } else { + toolbar_subtitle.visibility = View.VISIBLE + toolbar_subtitle.text = title + app_bar.elevation = if (showShadow) { + resources.getDimension(R.dimen.app_bar_elevation) + } else { + 0f + } + } + } + fun checkWifiSync() { if (!multiWallet!!.readBoolConfigValueForKey(Dcrlibwallet.SyncOnCellularConfigKey, Constants.DEF_SYNC_ON_CELLULAR)) { // Check if wifi is connected diff --git a/app/src/main/java/com/dcrandroid/dialog/send/AmountInputHelper.kt b/app/src/main/java/com/dcrandroid/dialog/send/AmountInputHelper.kt index 250ffaff7..81b3c4070 100644 --- a/app/src/main/java/com/dcrandroid/dialog/send/AmountInputHelper.kt +++ b/app/src/main/java/com/dcrandroid/dialog/send/AmountInputHelper.kt @@ -20,6 +20,7 @@ import com.dcrandroid.extensions.hide import com.dcrandroid.extensions.show import com.dcrandroid.extensions.toggleVisibility import com.dcrandroid.util.CoinFormat +import com.dcrandroid.util.CurrencyUtil import com.dcrandroid.util.GetExchangeRate import com.dcrandroid.util.WalletData import dcrlibwallet.Dcrlibwallet @@ -29,12 +30,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import java.math.BigDecimal -import java.math.RoundingMode import java.text.DecimalFormat const val AmountRelativeSize = 0.625f -val usdAmountFormat: DecimalFormat = DecimalFormat("0.0000") val usdAmountFormat2: DecimalFormat = DecimalFormat("0.00") val dcrFormat = DecimalFormat("#.########") @@ -194,7 +193,7 @@ class AmountInputHelper(private val layout: LinearLayout, private val scrollToBo layout.send_amount.removeTextChangedListener(this) dcrAmount = BigDecimal(coin) - usdAmount = dcrToUSD(exchangeDecimal, dcrAmount!!.toDouble()) + usdAmount = CurrencyUtil.dcrToUSD(exchangeDecimal, dcrAmount!!.toDouble()) if (currencyIsDCR) { val dcr = Dcrlibwallet.amountAtom(coin) @@ -252,10 +251,10 @@ class AmountInputHelper(private val layout: LinearLayout, private val scrollToBo if (enteredAmount != null) { if (currencyIsDCR) { dcrAmount = enteredAmount!! - usdAmount = dcrToUSD(exchangeDecimal, dcrAmount!!.toDouble()) + usdAmount = CurrencyUtil.dcrToUSD(exchangeDecimal, dcrAmount!!.toDouble()) } else { usdAmount = enteredAmount!! - dcrAmount = usdToDCR(exchangeDecimal, usdAmount!!.toDouble()) + dcrAmount = CurrencyUtil.usdToDCR(exchangeDecimal, usdAmount!!.toDouble()) } } else { dcrAmount = null @@ -312,7 +311,7 @@ class AmountInputHelper(private val layout: LinearLayout, private val scrollToBo } if (dcrAmount != null) { - usdAmount = dcrToUSD(exchangeDecimal, dcrAmount!!.toDouble()) + usdAmount = CurrencyUtil.dcrToUSD(exchangeDecimal, dcrAmount!!.toDouble()) } displayEquivalentValue() @@ -331,27 +330,27 @@ class AmountInputHelper(private val layout: LinearLayout, private val scrollToBo } } -fun dcrToFormattedUSD(exchangeDecimal: BigDecimal?, dcr: Double, scale: Int = 4): String { - if (scale == 4) { - return usdAmountFormat.format( - dcrToUSD(exchangeDecimal, dcr)!!.setScale(scale, BigDecimal.ROUND_HALF_EVEN).toDouble()) - } - - return usdAmountFormat2.format( - dcrToUSD(exchangeDecimal, dcr)!!.setScale(scale, BigDecimal.ROUND_HALF_EVEN).toDouble()) -} - -fun dcrToUSD(exchangeDecimal: BigDecimal?, dcr: Double): BigDecimal? { - val dcrDecimal = BigDecimal(dcr) - return exchangeDecimal?.multiply(dcrDecimal) -} - -fun usdToDCR(exchangeDecimal: BigDecimal?, usd: Double): BigDecimal? { - if (exchangeDecimal == null) { - return null - } - - val usdDecimal = BigDecimal(usd) - // using 8 to be safe - return usdDecimal.divide(exchangeDecimal, 8, RoundingMode.HALF_EVEN) -} \ No newline at end of file +//fun dcrToFormattedUSD(exchangeDecimal: BigDecimal?, dcr: Double, scale: Int = 4): String { +// if (scale == 4) { +// return usdAmountFormat.format( +// dcrToUSD(exchangeDecimal, dcr)!!.setScale(scale, BigDecimal.ROUND_HALF_EVEN).toDouble()) +// } +// +// return usdAmountFormat2.format( +// dcrToUSD(exchangeDecimal, dcr)!!.setScale(scale, BigDecimal.ROUND_HALF_EVEN).toDouble()) +//} +// +//fun dcrToUSD(exchangeDecimal: BigDecimal?, dcr: Double): BigDecimal? { +// val dcrDecimal = BigDecimal(dcr) +// return exchangeDecimal?.multiply(dcrDecimal) +//} +// +//fun usdToDCR(exchangeDecimal: BigDecimal?, usd: Double): BigDecimal? { +// if (exchangeDecimal == null) { +// return null +// } +// +// val usdDecimal = BigDecimal(usd) +// // using 8 to be safe +// return usdDecimal.divide(exchangeDecimal, 8, RoundingMode.HALF_EVEN) +//} \ No newline at end of file diff --git a/app/src/main/java/com/dcrandroid/dialog/send/ConfirmTransaction.kt b/app/src/main/java/com/dcrandroid/dialog/send/ConfirmTransaction.kt index cbaf53146..429f112fd 100644 --- a/app/src/main/java/com/dcrandroid/dialog/send/ConfirmTransaction.kt +++ b/app/src/main/java/com/dcrandroid/dialog/send/ConfirmTransaction.kt @@ -21,10 +21,7 @@ import com.dcrandroid.dialog.PasswordPromptDialog import com.dcrandroid.dialog.PinPromptDialog import com.dcrandroid.extensions.hide import com.dcrandroid.extensions.show -import com.dcrandroid.util.CoinFormat -import com.dcrandroid.util.PassPromptTitle -import com.dcrandroid.util.PassPromptUtil -import com.dcrandroid.util.Utils +import com.dcrandroid.util.* import dcrlibwallet.Dcrlibwallet import dcrlibwallet.Wallet import kotlinx.android.synthetic.main.confirm_send_sheet.* @@ -61,7 +58,7 @@ class ConfirmTransaction(private val fragmentActivity: FragmentActivity, val sen val dcrAmount = CoinFormat.formatDecred(Dcrlibwallet.amountAtom(transactionData.dcrAmount.toDouble())) val amountStr = if (transactionData.exchangeDecimal != null) { - val usdAmount = dcrToFormattedUSD(transactionData.exchangeDecimal, transactionData.dcrAmount.toDouble(), 2) + val usdAmount = CurrencyUtil.dcrToFormattedUSD(transactionData.exchangeDecimal, transactionData.dcrAmount.toDouble(), 2) HtmlCompat.fromHtml(getString(R.string.x_dcr_usd, dcrAmount, usdAmount), 0) } else { getString(R.string.x_dcr, dcrAmount) diff --git a/app/src/main/java/com/dcrandroid/dialog/send/SendDialog.kt b/app/src/main/java/com/dcrandroid/dialog/send/SendDialog.kt index b6bc42b88..283f0dc1d 100644 --- a/app/src/main/java/com/dcrandroid/dialog/send/SendDialog.kt +++ b/app/src/main/java/com/dcrandroid/dialog/send/SendDialog.kt @@ -30,6 +30,7 @@ import com.dcrandroid.dialog.InfoDialog import com.dcrandroid.extensions.hide import com.dcrandroid.extensions.show import com.dcrandroid.util.CoinFormat +import com.dcrandroid.util.CurrencyUtil import com.dcrandroid.util.SnackBar import com.dcrandroid.util.Utils import com.dcrandroid.view.util.AccountCustomSpinner @@ -405,8 +406,8 @@ class SendDialog(val fragmentActivity: FragmentActivity, dismissListener: Dialog val feeCoin = Dcrlibwallet.amountCoin(feeAtom) val totalCostCoin = Dcrlibwallet.amountCoin(totalCostAtom) - val feeUSD = dcrToFormattedUSD(amountHelper.exchangeDecimal, feeCoin) - val totalCostUSD = dcrToFormattedUSD(amountHelper.exchangeDecimal, totalCostCoin, 2) + val feeUSD = CurrencyUtil.dcrToFormattedUSD(amountHelper.exchangeDecimal, feeCoin) + val totalCostUSD = CurrencyUtil.dcrToFormattedUSD(amountHelper.exchangeDecimal, totalCostCoin, 2) feeSpanned = HtmlCompat.fromHtml(getString(R.string.x_dcr_usd, feeString, feeUSD), 0) totalCostSpanned = HtmlCompat.fromHtml(getString(R.string.x_dcr_usd, totalCostString, totalCostUSD), 0) diff --git a/app/src/main/java/com/dcrandroid/fragments/BaseFragment.kt b/app/src/main/java/com/dcrandroid/fragments/BaseFragment.kt index a2cee9100..299021003 100644 --- a/app/src/main/java/com/dcrandroid/fragments/BaseFragment.kt +++ b/app/src/main/java/com/dcrandroid/fragments/BaseFragment.kt @@ -66,6 +66,13 @@ open class BaseFragment : Fragment(), SyncProgressListener, TxAndBlockNotificati } } + fun setToolbarSubTitle(title: CharSequence, showShadow: Boolean) { + if (activity is HomeActivity) { + val homeActivity = activity as HomeActivity + homeActivity.setToolbarSubTitle(title, showShadow) + } + } + fun refreshNavigationTabs() { if (activity is HomeActivity) { val homeActivity = activity as HomeActivity diff --git a/app/src/main/java/com/dcrandroid/fragments/OverviewFragment.kt b/app/src/main/java/com/dcrandroid/fragments/OverviewFragment.kt index da7893c3d..e9c03ac0f 100644 --- a/app/src/main/java/com/dcrandroid/fragments/OverviewFragment.kt +++ b/app/src/main/java/com/dcrandroid/fragments/OverviewFragment.kt @@ -14,6 +14,7 @@ import android.view.ViewGroup import android.view.ViewTreeObserver import android.widget.LinearLayout import android.widget.TextView +import androidx.core.text.HtmlCompat import androidx.core.widget.NestedScrollView import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -24,10 +25,7 @@ import com.dcrandroid.data.Constants import com.dcrandroid.data.Transaction import com.dcrandroid.dialog.InfoDialog import com.dcrandroid.extensions.* -import com.dcrandroid.util.CoinFormat -import com.dcrandroid.util.Deserializer -import com.dcrandroid.util.SnackBar -import com.dcrandroid.util.SyncLayoutUtil +import com.dcrandroid.util.* import com.google.gson.GsonBuilder import dcrlibwallet.AccountMixerNotificationListener import dcrlibwallet.Dcrlibwallet @@ -40,10 +38,11 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import java.math.BigDecimal const val MAX_TRANSACTIONS = 3 -class OverviewFragment : BaseFragment(), ViewTreeObserver.OnScrollChangedListener, AccountMixerNotificationListener { +class OverviewFragment : BaseFragment(), ViewTreeObserver.OnScrollChangedListener, AccountMixerNotificationListener, GetExchangeRate.ExchangeRateCallback { companion object { private var closedBackupWarning = false @@ -65,9 +64,13 @@ class OverviewFragment : BaseFragment(), ViewTreeObserver.OnScrollChangedListene private lateinit var recyclerView: RecyclerView private lateinit var balanceTextView: TextView + private lateinit var usdBalanceTextView: TextView internal lateinit var noTransactionsTextView: TextView internal lateinit var transactionsLayout: LinearLayout + var exchangeEnabled = true + var exchangeDecimal: BigDecimal? = null + private lateinit var syncLayout: LinearLayout private var syncLayoutUtil: SyncLayoutUtil? = null @@ -80,6 +83,7 @@ class OverviewFragment : BaseFragment(), ViewTreeObserver.OnScrollChangedListene recyclerView = view.findViewById(R.id.rv_transactions) balanceTextView = view.findViewById(R.id.tv_visible_wallet_balance) + usdBalanceTextView = view.findViewById(R.id.tv_visible_usd_wallet_balance) noTransactionsTextView = view.findViewById(R.id.tv_no_transactions) transactionsLayout = view.findViewById(R.id.transactions_view) @@ -89,6 +93,8 @@ class OverviewFragment : BaseFragment(), ViewTreeObserver.OnScrollChangedListene override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) + fetchExchangeRate() + adapter = TransactionListAdapter(context!!, transactions) recyclerView.layoutManager = LinearLayoutManager(context) @@ -206,17 +212,32 @@ class OverviewFragment : BaseFragment(), ViewTreeObserver.OnScrollChangedListene } override fun onScrollChanged() { + val totalCostAtom = multiWallet!!.totalWalletBalance() + val totalCostCoin = Dcrlibwallet.amountCoin(totalCostAtom) + if (mainBalanceIsVisible()) { setToolbarTitle(CoinFormat.format(multiWallet!!.totalWalletBalance(), 0.7f), true) + if (isExchangeEnabled()) { + val formattedUSD = HtmlCompat.fromHtml(getString(R.string.dcr_usd, CurrencyUtil.dcrToFormattedUSD(exchangeDecimal, totalCostCoin, 2)), 0) + setToolbarSubTitle(formattedUSD, true) + } } else { setToolbarTitle(R.string.overview, false) + setToolbarSubTitle("", false) } } private fun loadBalance() = GlobalScope.launch(Dispatchers.Main) { balanceTextView.text = CoinFormat.format(multiWallet!!.totalWalletBalance(), 0.5f) + val totalCostAtom = multiWallet!!.totalWalletBalance() + val totalCostCoin = Dcrlibwallet.amountCoin(totalCostAtom) + if (mainBalanceIsVisible()) { setToolbarTitle(CoinFormat.format(multiWallet!!.totalWalletBalance(), 0.7f), true) + if (isExchangeEnabled()) { + val formattedUSD = HtmlCompat.fromHtml(getString(R.string.dcr_usd, CurrencyUtil.dcrToFormattedUSD(exchangeDecimal, totalCostCoin, 2)), 0) + setToolbarSubTitle(formattedUSD, true) + } } } @@ -323,6 +344,46 @@ class OverviewFragment : BaseFragment(), ViewTreeObserver.OnScrollChangedListene override fun onAccountMixerStarted(walletID: Long) { setMixerStatus() } + + private fun isExchangeEnabled(): Boolean { + val multiWallet = WalletData.multiWallet!! + val currencyConversion = multiWallet.readInt32ConfigValueForKey(Dcrlibwallet.CurrencyConversionConfigKey, Constants.DEF_CURRENCY_CONVERSION) + + exchangeEnabled = currencyConversion > 0 + + return exchangeEnabled + } + + private fun fetchExchangeRate() { + if (!isExchangeEnabled()) { + return + } + + println("Getting exchange rate") + val userAgent = multiWallet!!.readStringConfigValueForKey(Dcrlibwallet.UserAgentConfigKey) + GetExchangeRate(userAgent, this).execute() + } + + override fun onExchangeRateSuccess(rate: GetExchangeRate.BittrexRateParser) { + exchangeDecimal = rate.usdRate + + val totalCostAtom = multiWallet!!.totalWalletBalance() + val totalCostCoin = Dcrlibwallet.amountCoin(totalCostAtom) + val formattedUSD = HtmlCompat.fromHtml(getString(R.string.dcr_usd, CurrencyUtil.dcrToFormattedUSD(exchangeDecimal, totalCostCoin, 2)), 0) + usdBalanceTextView.text = formattedUSD + + GlobalScope.launch(Dispatchers.Main) { + usdBalanceTextView.show() + } + } + + override fun onExchangeRateError(e: Exception) { + e.printStackTrace() + + GlobalScope.launch(Dispatchers.Main) { + usdBalanceTextView.hide() + } + } } fun OverviewFragment.showTransactionList() = GlobalScope.launch(Dispatchers.Main) { diff --git a/app/src/main/java/com/dcrandroid/util/CurrencyUtil.kt b/app/src/main/java/com/dcrandroid/util/CurrencyUtil.kt new file mode 100644 index 000000000..457ca7e58 --- /dev/null +++ b/app/src/main/java/com/dcrandroid/util/CurrencyUtil.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018-2019 The Decred developers + * Use of this source code is governed by an ISC + * license that can be found in the LICENSE file. + */ + +package com.dcrandroid.util + +import java.math.BigDecimal +import java.math.RoundingMode +import java.text.DecimalFormat + +val usdAmountFormat: DecimalFormat = DecimalFormat("###,###,###,###,###.####") +val usdAmountFormat2: DecimalFormat = DecimalFormat("###,###,###,###,###.##") + +object CurrencyUtil { + fun dcrToFormattedUSD(exchangeDecimal: BigDecimal?, dcr: Double, scale: Int = 4): String { + if (scale == 4) { + return usdAmountFormat.format( + dcrToUSD(exchangeDecimal, dcr)!!.setScale(scale, BigDecimal.ROUND_HALF_EVEN).toDouble()) + } + return usdAmountFormat2.format( + dcrToUSD(exchangeDecimal, dcr)!!.setScale(scale, BigDecimal.ROUND_HALF_EVEN).toDouble()) + } + + fun dcrToUSD(exchangeDecimal: BigDecimal?, dcr: Double): BigDecimal? { + val dcrDecimal = BigDecimal(dcr) + return exchangeDecimal?.multiply(dcrDecimal) + } + + fun usdToDCR(exchangeDecimal: BigDecimal?, usd: Double): BigDecimal? { + if (exchangeDecimal == null) { + return null + } + + val usdDecimal = BigDecimal(usd) + // using 8 to be safe + return usdDecimal.divide(exchangeDecimal, 8, RoundingMode.HALF_EVEN) + } +} diff --git a/app/src/main/res/drawable/light_grey_border_8dp.xml b/app/src/main/res/drawable/light_grey_border_8dp.xml new file mode 100644 index 000000000..913ecf299 --- /dev/null +++ b/app/src/main/res/drawable/light_grey_border_8dp.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/layout/activity_tabs.xml b/app/src/main/res/layout/activity_tabs.xml index e9cfb5582..959ea4548 100644 --- a/app/src/main/res/layout/activity_tabs.xml +++ b/app/src/main/res/layout/activity_tabs.xml @@ -1,5 +1,4 @@ - -