diff --git a/app/src/main/java/com/brainwallet/data/model/Fee.kt b/app/src/main/java/com/brainwallet/data/model/Fee.kt index 246100a4..0ea99667 100644 --- a/app/src/main/java/com/brainwallet/data/model/Fee.kt +++ b/app/src/main/java/com/brainwallet/data/model/Fee.kt @@ -1,20 +1,27 @@ package com.brainwallet.data.model +import android.annotation.SuppressLint +import com.brainwallet.R +import com.brainwallet.tools.manager.FeeManager.ECONOMY +import com.brainwallet.tools.manager.FeeManager.FeeType +import com.brainwallet.tools.manager.FeeManager.LUXURY +import com.brainwallet.tools.manager.FeeManager.REGULAR import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import kotlin.math.ceil +import kotlin.math.round @Serializable data class Fee( @JvmField - @SerialName("fee_per_kb") + @SerialName("fee_per_kb_luxury") var luxury: Long, @JvmField - @SerialName("fee_per_kb_economy") + @SerialName("fee_per_kb") var regular: Long, @JvmField - @SerialName("fee_per_kb_luxury") + @SerialName("fee_per_kb_economy") var economy: Long, - var timestamp: Long ) { companion object { //from legacy @@ -25,13 +32,52 @@ data class Fee( private const val defaultLuxuryFeePerKB: Long = 66746L private const val defaultTimestamp: Long = 1583015199122L +// {"fee_per_kb":5289,"fee_per_kb_economy":2645,"fee_per_kb_luxury":10578} + @JvmStatic val Default = Fee( defaultLuxuryFeePerKB, defaultRegularFeePerKB, defaultEconomyFeePerKB, - defaultTimestamp ) - } } + + +data class FeeOption( + @FeeType + val type: String, + val feePerKb: Long, + val labelStringId: Int, +) + +fun Fee.toFeeOptions(): List = listOf( + FeeOption( + type = ECONOMY, + feePerKb = economy, + labelStringId = R.string.network_fee_options_low + ), + FeeOption( + type = REGULAR, + feePerKb = regular, + labelStringId = R.string.network_fee_options_medium + ), + FeeOption( + type = LUXURY, + feePerKb = luxury, + labelStringId = R.string.network_fee_options_top + ), +) + +fun FeeOption.getFiat(currencyEntity: CurrencyEntity): Float { + val satoshisPerLtc = 100_000_000.0 + val feeInLtc = feePerKb / satoshisPerLtc + return (feeInLtc * currencyEntity.rate).toFloat() +} + +@SuppressLint("DefaultLocale") +fun FeeOption.getFiatFormatted(currencyEntity: CurrencyEntity): String { + val fiatValue = getFiat(currencyEntity) + val formatted = String.format("%.3f", fiatValue) + return "${currencyEntity.symbol}$formatted" +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/data/repository/LtcRepository.kt b/app/src/main/java/com/brainwallet/data/repository/LtcRepository.kt index 31c05e30..38b325fd 100644 --- a/app/src/main/java/com/brainwallet/data/repository/LtcRepository.kt +++ b/app/src/main/java/com/brainwallet/data/repository/LtcRepository.kt @@ -1,12 +1,16 @@ package com.brainwallet.data.repository import android.content.Context +import android.content.SharedPreferences +import androidx.core.content.edit import com.brainwallet.data.model.CurrencyEntity import com.brainwallet.data.model.Fee import com.brainwallet.data.source.RemoteApiSource +import com.brainwallet.di.json import com.brainwallet.tools.manager.BRSharedPrefs import com.brainwallet.tools.manager.FeeManager import com.brainwallet.tools.sqlite.CurrencyDataSource +import kotlinx.serialization.encodeToString interface LtcRepository { suspend fun fetchRates(): List @@ -16,7 +20,8 @@ interface LtcRepository { class Impl( private val context: Context, private val remoteApiSource: RemoteApiSource, - private val currencyDataSource: CurrencyDataSource + private val currencyDataSource: CurrencyDataSource, + private val sharedPreferences: SharedPreferences, ) : LtcRepository { //todo: make it offline first here later, currently just using CurrencyDataSource.getAllCurrencies @@ -42,18 +47,33 @@ interface LtcRepository { } override suspend fun fetchFeePerKb(): Fee { + val lastUpdateTime = sharedPreferences.getLong(PREF_KEY_NETWORK_FEE_PER_KB_CACHED_AT, 0) + val currentTime = System.currentTimeMillis() + val cachedFee = sharedPreferences.getString(PREF_KEY_NETWORK_FEE_PER_KB, null) + ?.let { json.decodeFromString(it) } + return runCatching { - val fee = remoteApiSource.getFeePerKb() + // Check if cache exists and is less than 6 hours old + if (cachedFee != null && (currentTime - lastUpdateTime) < 6 * 60 * 60 * 1000) { + return cachedFee + } - //todo: cache + val fee = remoteApiSource.getFeePerKb() + sharedPreferences.edit { + putString(PREF_KEY_NETWORK_FEE_PER_KB, json.encodeToString(fee)) + putLong(PREF_KEY_NETWORK_FEE_PER_KB_CACHED_AT, currentTime) + } return fee - }.getOrElse { Fee.Default } + }.getOrElse { + cachedFee ?: Fee.Default + } } } companion object { - + const val PREF_KEY_NETWORK_FEE_PER_KB = "network_fee_per_kb" + const val PREF_KEY_NETWORK_FEE_PER_KB_CACHED_AT = "${PREF_KEY_NETWORK_FEE_PER_KB}_cached_at" } } \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/di/Module.kt b/app/src/main/java/com/brainwallet/di/Module.kt index 4dce30f1..05194b2d 100644 --- a/app/src/main/java/com/brainwallet/di/Module.kt +++ b/app/src/main/java/com/brainwallet/di/Module.kt @@ -58,7 +58,7 @@ val dataModule = module { single { CurrencyDataSource.getInstance(get()) } single { provideSharedPreferences(context = androidApplication()) } single { SettingRepository.Impl(get(), get()) } - single { LtcRepository.Impl(get(), get(), get()) } + single { LtcRepository.Impl(get(), get(), get(), get()) } } val viewModelModule = module { diff --git a/app/src/main/java/com/brainwallet/presenter/fragments/FragmentSend.kt b/app/src/main/java/com/brainwallet/presenter/fragments/FragmentSend.kt index 1f4af687..9b47690e 100644 --- a/app/src/main/java/com/brainwallet/presenter/fragments/FragmentSend.kt +++ b/app/src/main/java/com/brainwallet/presenter/fragments/FragmentSend.kt @@ -11,9 +11,12 @@ import android.view.ViewGroup import android.view.ViewTreeObserver.OnGlobalLayoutListener import android.view.animation.OvershootInterpolator import android.view.inputmethod.EditorInfo -import android.widget.* -import androidx.annotation.ColorRes -import androidx.annotation.StringRes +import android.widget.Button +import android.widget.EditText +import android.widget.ImageButton +import android.widget.LinearLayout +import android.widget.ScrollView +import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.fragment.app.Fragment @@ -22,38 +25,53 @@ import androidx.transition.Transition import androidx.transition.TransitionManager import com.brainwallet.R import com.brainwallet.presenter.customviews.BRKeyboard -import com.brainwallet.presenter.customviews.BRLinearLayoutWithCaret import com.brainwallet.presenter.entities.ServiceItems import com.brainwallet.presenter.entities.TransactionItem import com.brainwallet.tools.animation.BRAnimator import com.brainwallet.tools.animation.BRDialog import com.brainwallet.tools.animation.SlideDetector import com.brainwallet.tools.animation.SpringAnimator -import com.brainwallet.tools.manager.* +import com.brainwallet.tools.manager.AnalyticsManager +import com.brainwallet.tools.manager.BRClipboardManager +import com.brainwallet.tools.manager.BRSharedPrefs +import com.brainwallet.tools.manager.FeeManager import com.brainwallet.tools.security.BRSender import com.brainwallet.tools.security.BitcoinUrlHandler import com.brainwallet.tools.threads.BRExecutor -import com.brainwallet.tools.util.* +import com.brainwallet.tools.util.BRConstants +import com.brainwallet.tools.util.BRCurrency +import com.brainwallet.tools.util.BRExchange +import com.brainwallet.tools.util.Utils import com.brainwallet.wallet.BRWalletManager -import com.google.common.math.Quantiles.scale import timber.log.Timber import java.math.BigDecimal import java.math.RoundingMode import java.util.regex.Pattern +//TODO: make sure remove unused after refactor network fee move to HomeSettingDrawerSheet class FragmentSend : Fragment() { - private lateinit var signalLayout: LinearLayout; private lateinit var keyboardLayout: LinearLayout - private lateinit var scanButton: Button; private lateinit var pasteButton: Button; private lateinit var sendButton: Button; private lateinit var isoCurrencySymbolButton: Button - private lateinit var commentEdit: EditText; private lateinit var addressEdit: EditText;private lateinit var amountEdit: EditText - private lateinit var isoCurrencySymbolText: TextView; private lateinit var balanceText: TextView; private lateinit var feeText: TextView; private lateinit var feeDescription: TextView; private lateinit var warningText: TextView - private var amountLabelOn = true; private var ignoreCleanup = false; private var feeButtonsShown = false - private lateinit var edit: ImageView + private lateinit var signalLayout: LinearLayout; + private lateinit var keyboardLayout: LinearLayout + private lateinit var scanButton: Button; + private lateinit var pasteButton: Button; + private lateinit var sendButton: Button; + private lateinit var isoCurrencySymbolButton: Button + private lateinit var commentEdit: EditText; + private lateinit var addressEdit: EditText; + private lateinit var amountEdit: EditText + private lateinit var isoCurrencySymbolText: TextView; + private lateinit var balanceText: TextView; + private lateinit var feeText: TextView; + private lateinit var feeDescription: TextView; + private lateinit var warningText: TextView + private var amountLabelOn = true; + private var ignoreCleanup = false; + private var feeButtonsShown = false private var currentBalance: Long = 0 private var keyboardIndex = 0 private lateinit var keyboard: BRKeyboard private lateinit var closeButton: ImageButton private lateinit var amountLayout: ConstraintLayout - private lateinit var feeLayout: BRLinearLayoutWithCaret private var selectedIsoCurrencySymbol: String? = null private lateinit var backgroundLayout: ScrollView private lateinit var amountBuilder: StringBuilder @@ -78,16 +96,17 @@ class FragmentSend : Fragment() { amountEdit = rootView.findViewById(R.id.amount_edit) as EditText balanceText = rootView.findViewById(R.id.balance_text) as TextView feeText = rootView.findViewById(R.id.fee_text) as TextView - edit = rootView.findViewById(R.id.edit) as ImageView isoCurrencySymbolButton = rootView.findViewById(R.id.iso_button) as Button keyboardLayout = rootView.findViewById(R.id.keyboard_layout) as LinearLayout amountLayout = rootView.findViewById(R.id.amount_layout) as ConstraintLayout - feeLayout = rootView.findViewById(R.id.fee_buttons_layout) as BRLinearLayoutWithCaret - feeDescription = rootView.findViewById(R.id.fee_description) as TextView - warningText = rootView.findViewById(R.id.warning_text) as TextView +// feeLayout = rootView.findViewById(R.id.fee_buttons_layout) as BRLinearLayoutWithCaret +// feeDescription = rootView.findViewById(R.id.fee_description) as TextView +// warningText = rootView.findViewById(R.id.warning_text) as TextView closeButton = rootView.findViewById(R.id.close_button) as ImageButton selectedIsoCurrencySymbol = - if (BRSharedPrefs.getPreferredLTC(context)) "LTC" else BRSharedPrefs.getIsoSymbol(context) + if (BRSharedPrefs.getPreferredLTC(context)) "LTC" else BRSharedPrefs.getIsoSymbol( + context + ) amountBuilder = StringBuilder(0) setListeners() @@ -102,18 +121,20 @@ class FragmentSend : Fragment() { signalLayout.setOnTouchListener(SlideDetector(signalLayout) { animateClose() }) AnalyticsManager.logCustomEvent(BRConstants._20191105_VSC) - setupFeesSelector(rootView) - showFeeSelectionButtons(feeButtonsShown) - edit.setOnClickListener { - feeButtonsShown = !feeButtonsShown - showFeeSelectionButtons(feeButtonsShown) - } +// setupFeesSelector(rootView) +// showFeeSelectionButtons(feeButtonsShown) +// edit.setOnClickListener { +// feeButtonsShown = !feeButtonsShown +// showFeeSelectionButtons(feeButtonsShown) +// } keyboardIndex = signalLayout.indexOfChild(keyboardLayout) // TODO: all views are using the layout of this button. Views should be refactored without it // Hiding until layouts are built. showKeyboard(false) signalLayout.layoutTransition = BRAnimator.getDefaultTransition() - + + updateText() + return rootView } @@ -121,62 +142,62 @@ class FragmentSend : Fragment() { super.onActivityCreated(savedInstanceState) } - private fun setupFeesSelector(rootView: View) { - val feesSegment = rootView.findViewById(R.id.fees_segment) - feesSegment.setOnCheckedChangeListener { _, checkedTypeId -> onFeeTypeSelected(checkedTypeId) } - onFeeTypeSelected(R.id.regular_fee_but) - } - - private fun onFeeTypeSelected(checkedTypeId: Int) { - val feeManager = FeeManager.getInstance() - when (checkedTypeId) { - R.id.regular_fee_but -> { - feeManager.setFeeType(FeeManager.REGULAR) - BRWalletManager.getInstance().setFeePerKb(feeManager.currentFees.regular) - setFeeInformation(R.string.FeeSelector_regularTime, 0, 0, View.GONE) - } - R.id.economy_fee_but -> { - feeManager.setFeeType(FeeManager.ECONOMY) - BRWalletManager.getInstance().setFeePerKb(feeManager.currentFees.economy) - setFeeInformation( - R.string.FeeSelector_economyTime, - R.string.FeeSelector_economyWarning, - R.color.chili, - View.VISIBLE, - ) - } - R.id.luxury_fee_but -> { - feeManager.setFeeType(FeeManager.LUXURY) - BRWalletManager.getInstance().setFeePerKb(feeManager.currentFees.luxury) - setFeeInformation( - R.string.FeeSelector_luxuryTime, - R.string.FeeSelector_luxuryMessage, - R.color.cheddar, - View.VISIBLE, - ) - } - else -> { - } - } - updateText() - } - - private fun setFeeInformation( - @StringRes deliveryTime: Int, - @StringRes warningStringId: Int, - @ColorRes warningColorId: Int, - visibility: Int, - ) { - feeDescription.text = - getString(R.string.FeeSelector_estimatedDeliver, getString(deliveryTime)) - if (warningStringId != 0) { - warningText.setText(warningStringId) - } - if (warningColorId != 0) { - warningText.setTextColor(resources.getColor(warningColorId, null)) - } - warningText.visibility = visibility - } +// private fun setupFeesSelector(rootView: View) { +// val feesSegment = rootView.findViewById(R.id.fees_segment) +// feesSegment.setOnCheckedChangeListener { _, checkedTypeId -> onFeeTypeSelected(checkedTypeId) } +// onFeeTypeSelected(R.id.regular_fee_but) +// } + +// private fun onFeeTypeSelected(checkedTypeId: Int) { +// val feeManager = FeeManager.getInstance() +// when (checkedTypeId) { +// R.id.regular_fee_but -> { +// feeManager.setFeeType(FeeManager.REGULAR) +// BRWalletManager.getInstance().setFeePerKb(feeManager.currentFeeOptions.regular) +// setFeeInformation(R.string.FeeSelector_regularTime, 0, 0, View.GONE) +// } +// R.id.economy_fee_but -> { +// feeManager.setFeeType(FeeManager.ECONOMY) +// BRWalletManager.getInstance().setFeePerKb(feeManager.currentFeeOptions.economy) +// setFeeInformation( +// R.string.FeeSelector_economyTime, +// R.string.FeeSelector_economyWarning, +// R.color.chili, +// View.VISIBLE, +// ) +// } +// R.id.luxury_fee_but -> { +// feeManager.setFeeType(FeeManager.LUXURY) +// BRWalletManager.getInstance().setFeePerKb(feeManager.currentFeeOptions.luxury) +// setFeeInformation( +// R.string.FeeSelector_luxuryTime, +// R.string.FeeSelector_luxuryMessage, +// R.color.cheddar, +// View.VISIBLE, +// ) +// } +// else -> { +// } +// } +// updateText() +// } + +// private fun setFeeInformation( +// @StringRes deliveryTime: Int, +// @StringRes warningStringId: Int, +// @ColorRes warningColorId: Int, +// visibility: Int, +// ) { +// feeDescription.text = +// getString(R.string.FeeSelector_estimatedDeliver, getString(deliveryTime)) +// if (warningStringId != 0) { +// warningText.setText(warningStringId) +// } +// if (warningColorId != 0) { +// warningText.setTextColor(resources.getColor(warningColorId, null)) +// } +// warningText.visibility = visibility +// } private fun setListeners() { amountEdit.setOnClickListener { @@ -187,8 +208,9 @@ class FragmentSend : Fragment() { amountEdit.textSize = 24f balanceText.visibility = View.VISIBLE feeText.visibility = View.VISIBLE - edit.visibility = View.VISIBLE - isoCurrencySymbolText.text = BRCurrency.getSymbolByIso(activity, selectedIsoCurrencySymbol) +// edit.visibility = View.VISIBLE + isoCurrencySymbolText.text = + BRCurrency.getSymbolByIso(activity, selectedIsoCurrencySymbol) isoCurrencySymbolText.textSize = 28f val scaleX = amountEdit.scaleX amountEdit.scaleX = 0f @@ -242,7 +264,13 @@ class FragmentSend : Fragment() { ConstraintSet.TOP, px4, ) - set.connect(isoCurrencySymbolText.id, ConstraintSet.BOTTOM, -1, ConstraintSet.TOP, -1) + set.connect( + isoCurrencySymbolText.id, + ConstraintSet.BOTTOM, + -1, + ConstraintSet.TOP, + -1 + ) set.applyTo(amountLayout) } } @@ -328,7 +356,11 @@ class FragmentSend : Fragment() { ) isoCurrencySymbolButton.setOnClickListener { selectedIsoCurrencySymbol = - if (selectedIsoCurrencySymbol.equals(BRSharedPrefs.getIsoSymbol(context), ignoreCase = true)) { + if (selectedIsoCurrencySymbol.equals( + BRSharedPrefs.getIsoSymbol(context), + ignoreCase = true + ) + ) { "LTC" } else { BRSharedPrefs.getIsoSymbol(context) @@ -372,7 +404,8 @@ class FragmentSend : Fragment() { if (allFilled) { BRSender.getInstance().sendTransaction( context, - TransactionItem(sendAddress, + TransactionItem( + sendAddress, Utils.fetchServiceItem(context, ServiceItems.WALLETOPS), null, litoshiAmount.toLong(), @@ -490,9 +523,11 @@ class FragmentSend : Fragment() { key.isEmpty() -> { handleDeleteClick() } + Character.isDigit(key[0]) -> { handleDigitClick(key.substring(0, 1).toInt()) } + key[0] == '.' -> { handleSeparatorClick() } @@ -537,7 +572,7 @@ class FragmentSend : Fragment() { private fun updateText() { if (activity == null) return var tempDoubleAmountValue = 0.0 - if (amountBuilder.toString() != "" && amountBuilder.toString() != "." ) { + if (amountBuilder.toString() != "" && amountBuilder.toString() != ".") { tempDoubleAmountValue = amountBuilder.toString().toDouble() } val scaleValue = 4 @@ -547,42 +582,68 @@ class FragmentSend : Fragment() { val selectedISOSymbol = selectedIsoCurrencySymbol val currencySymbol = BRCurrency.getSymbolByIso(activity, selectedIsoCurrencySymbol) if (!amountLabelOn) isoCurrencySymbolText.text = currencySymbol - isoCurrencySymbolButton.text = String.format("%s(%s)", - BRCurrency.getCurrencyName(activity, selectedIsoCurrencySymbol), - currencySymbol) + isoCurrencySymbolButton.text = String.format( + "%s(%s)", + BRCurrency.getCurrencyName(activity, selectedIsoCurrencySymbol), + currencySymbol + ) // Balance depending on ISOSymbol currentBalance = BRWalletManager.getInstance().getBalance(activity) - val balanceForISOSymbol = BRExchange.getAmountFromLitoshis(activity, selectedISOSymbol, BigDecimal(currentBalance)) - val formattedBalance = BRCurrency.getFormattedCurrencyString(activity, selectedISOSymbol, balanceForISOSymbol) + val balanceForISOSymbol = BRExchange.getAmountFromLitoshis( + activity, + selectedISOSymbol, + BigDecimal(currentBalance) + ) + val formattedBalance = + BRCurrency.getFormattedCurrencyString(activity, selectedISOSymbol, balanceForISOSymbol) // Current amount depending on ISOSymbol val currentAmountInLitoshis = if (selectedIsoCurrencySymbol.equals("LTC", ignoreCase = true)) { BRExchange.convertltcsToLitoshis(tempDoubleAmountValue).toLong() } else { - BRExchange.getLitoshisFromAmount(activity,selectedIsoCurrencySymbol,BigDecimal(tempDoubleAmountValue)).toLong() + BRExchange.getLitoshisFromAmount( + activity, + selectedIsoCurrencySymbol, + BigDecimal(tempDoubleAmountValue) + ).toLong() } - Timber.d("timber: updateText: currentAmountInLitoshis %d",currentAmountInLitoshis) + Timber.d("timber: updateText: currentAmountInLitoshis %d", currentAmountInLitoshis) // Network Fee depending on ISOSymbol - var networkFee = if(currentAmountInLitoshis > 0) { BRWalletManager.getInstance().feeForTransactionAmount(currentAmountInLitoshis) } - else { 0 } //Amount is zero so network fee is also zero + var networkFee = if (currentAmountInLitoshis > 0) { + BRWalletManager.getInstance().feeForTransactionAmount(currentAmountInLitoshis) + } else { + 0 + } //Amount is zero so network fee is also zero val networkFeeForISOSymbol = - BRExchange.getAmountFromLitoshis(activity,selectedISOSymbol, BigDecimal(networkFee)).setScale(scaleValue, RoundingMode.HALF_UP) - val formattedNetworkFee = BRCurrency.getFormattedCurrencyString(activity, selectedISOSymbol, networkFeeForISOSymbol) + BRExchange.getAmountFromLitoshis(activity, selectedISOSymbol, BigDecimal(networkFee)) + .setScale(scaleValue, RoundingMode.HALF_UP) + val formattedNetworkFee = BRCurrency.getFormattedCurrencyString( + activity, + selectedISOSymbol, + networkFeeForISOSymbol + ) // Service Fee depending on ISOSymbol var serviceFee = Utils.tieredOpsFee(activity, currentAmountInLitoshis) val serviceFeeForISOSymbol = - BRExchange.getAmountFromLitoshis(activity,selectedISOSymbol,BigDecimal(serviceFee)).setScale(scaleValue, RoundingMode.HALF_UP) - val formattedServiceFee = BRCurrency.getFormattedCurrencyString(activity, selectedISOSymbol, serviceFeeForISOSymbol) + BRExchange.getAmountFromLitoshis(activity, selectedISOSymbol, BigDecimal(serviceFee)) + .setScale(scaleValue, RoundingMode.HALF_UP) + val formattedServiceFee = BRCurrency.getFormattedCurrencyString( + activity, + selectedISOSymbol, + serviceFeeForISOSymbol + ) // Total Fees depending on ISOSymbol val totalFees = networkFee + serviceFee val totalFeeForISOSymbol = - BRExchange.getAmountFromLitoshis( activity,selectedISOSymbol,BigDecimal(totalFees)).setScale(scaleValue, RoundingMode.HALF_UP) - val formattedTotalFees = BRCurrency.getFormattedCurrencyString(activity, selectedISOSymbol, totalFeeForISOSymbol) + BRExchange.getAmountFromLitoshis(activity, selectedISOSymbol, BigDecimal(totalFees)) + .setScale(scaleValue, RoundingMode.HALF_UP) + val formattedTotalFees = + BRCurrency.getFormattedCurrencyString(activity, selectedISOSymbol, totalFeeForISOSymbol) // Update UI with alert red when over balance if (BigDecimal(currentAmountInLitoshis).toDouble() > currentBalance.toDouble()) { @@ -590,8 +651,7 @@ class FragmentSend : Fragment() { feeText.setTextColor(requireContext().getColor(R.color.chili)) amountEdit.setTextColor(requireContext().getColor(R.color.chili)) if (!amountLabelOn) isoCurrencySymbolText.setTextColor(requireContext().getColor(R.color.chili)) - } - else { + } else { balanceText.setTextColor(requireContext().getColor(R.color.cheddar)) feeText.setTextColor(requireContext().getColor(R.color.cheddar)) amountEdit.setTextColor(requireContext().getColor(R.color.cheddar)) @@ -599,12 +659,14 @@ class FragmentSend : Fragment() { } balanceText.text = getString(R.string.Send_balance, formattedBalance) - feeText.text = String.format("(%s + %s): %s + %s = %s", + feeText.text = String.format( + "(%s + %s): %s + %s = %s", getString(R.string.Network_feeLabel), getString(R.string.Fees_Service), formattedNetworkFee, formattedServiceFee, - formattedTotalFees) + formattedTotalFees + ) amountLayout.requestLayout() } @@ -627,13 +689,13 @@ class FragmentSend : Fragment() { } } - private fun showFeeSelectionButtons(b: Boolean) { - if (!b) { - signalLayout.removeView(feeLayout) - } else { - signalLayout.addView(feeLayout, signalLayout.indexOfChild(amountLayout) + 1) - } - } +// private fun showFeeSelectionButtons(b: Boolean) { +// if (!b) { +// signalLayout.removeView(feeLayout) +// } else { +// signalLayout.addView(feeLayout, signalLayout.indexOfChild(amountLayout) + 1) +// } +// } private fun setAmount() { val tmpAmount = amountBuilder.toString() @@ -648,7 +710,7 @@ class FragmentSend : Fragment() { newAmount.append(",") } } - + amountEdit.setText(newAmount.toString()) } @@ -680,7 +742,8 @@ class FragmentSend : Fragment() { private fun loadMetaData() { ignoreCleanup = false if (!Utils.isNullOrEmpty(savedMemo)) commentEdit.setText(savedMemo) - if (!Utils.isNullOrEmpty(savedIsoCurrencySymbol)) selectedIsoCurrencySymbol = savedIsoCurrencySymbol + if (!Utils.isNullOrEmpty(savedIsoCurrencySymbol)) selectedIsoCurrencySymbol = + savedIsoCurrencySymbol if (!Utils.isNullOrEmpty(savedAmount)) { amountBuilder = StringBuilder(savedAmount!!) Handler().postDelayed({ @@ -709,7 +772,6 @@ class FragmentSend : Fragment() { } - ///DEV WIP // val approximateNetworkFee = BRCurrency.getFormattedCurrencyString(activity, selectedISOSymbol, feeForISOSymbol) diff --git a/app/src/main/java/com/brainwallet/tools/manager/FeeManager.java b/app/src/main/java/com/brainwallet/tools/manager/FeeManager.java index 963a56af..f9457baa 100644 --- a/app/src/main/java/com/brainwallet/tools/manager/FeeManager.java +++ b/app/src/main/java/com/brainwallet/tools/manager/FeeManager.java @@ -5,34 +5,23 @@ import androidx.annotation.StringDef; import com.brainwallet.data.repository.LtcRepository; -import com.brainwallet.presenter.entities.ServiceItems; import com.brainwallet.tools.threads.BRExecutor; -import com.brainwallet.tools.util.Utils; import com.brainwallet.data.model.Fee; -import com.platform.APIClient; import org.koin.java.KoinJavaComponent; -import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - -import okhttp3.Request; -import okhttp3.Response; -import timber.log.Timber; //we are still using this, maybe in the future will deprecate? +@Deprecated public final class FeeManager { private static final FeeManager instance; private String feeType; - public Fee currentFees; + public Fee currentFeeOptions; public static FeeManager getInstance() { return instance; @@ -44,8 +33,8 @@ public static FeeManager getInstance() { } private void initWithDefaultValues() { - currentFees = Fee.getDefault(); - feeType = REGULAR; + currentFeeOptions = Fee.getDefault(); + feeType = LUXURY; } private FeeManager() { @@ -56,37 +45,22 @@ public void setFeeType(@FeeType String feeType) { } public void resetFeeType() { - this.feeType = REGULAR; + this.feeType = LUXURY; } - public boolean isRegularFee() { - return feeType.equals(REGULAR); + public boolean isLuxuryFee() { + return feeType.equals(LUXURY); } - public static final String LUXURY = "luxury"; - public static final String REGULAR = "regular"; - public static final String ECONOMY = "economy"; + public static final String LUXURY = "luxury";//top + public static final String REGULAR = "regular";//medium + public static final String ECONOMY = "economy";//low public void setFees(long luxuryFee, long regularFee, long economyFee) { - // TODO: to be implemented when feePerKB API will be ready - currentFees = new Fee(luxuryFee, regularFee, economyFee, System.currentTimeMillis()); + currentFeeOptions = new Fee(luxuryFee, regularFee, economyFee); } public static void updateFeePerKb(Context app) { - -// String jsonString = "{'fee_per_kb': 10000, 'fee_per_kb_economy': 2500, 'fee_per_kb_luxury': 66746}"; -// try { -// JSONObject obj = new JSONObject(jsonString); -// // TODO: Refactor when mobile-api v0.4.0 is in prod -// long regularFee = obj.optLong("fee_per_kb"); -// long economyFee = obj.optLong("fee_per_kb_economy"); -// long luxuryFee = obj.optLong("fee_per_kb_luxury"); -// FeeManager.getInstance().setFees(luxuryFee, regularFee, economyFee); -// BRSharedPrefs.putFeeTime(app, System.currentTimeMillis()); //store the time of the last successful fee fetch -// } catch (JSONException e) { -// Timber.e(new IllegalArgumentException("updateFeePerKb: FAILED: " + jsonString, e)); -// } - LtcRepository ltcRepository = KoinJavaComponent.get(LtcRepository.class); BRExecutor.getInstance().executeSuspend( (coroutineScope, continuation) -> ltcRepository.fetchFeePerKb(continuation) @@ -98,43 +72,6 @@ public static void updateFeePerKb(Context app) { }); } - // createGETRequestURL - // Creates the params and headers to make a GET Request - @Deprecated - private static String createGETRequestURL(Context app, String myURL) { - Request request = new Request.Builder() - .url(myURL) - .header("Content-Type", "application/json") - .header("Accept", "application/json") - .header("User-agent", Utils.getAgentString(app, "android/HttpURLConnection")) - .header("BW-client-code", Utils.fetchServiceItem(app, ServiceItems.CLIENTCODE)) - .get().build(); - String response = null; - Response resp = APIClient.getInstance(app).sendRequest(request, false, 0); - - try { - if (resp == null) { - Timber.i("timber: urlGET: %s resp is null", myURL); - return null; - } - response = resp.body().string(); - String strDate = resp.header("date"); - if (strDate == null) { - Timber.i("timber: urlGET: strDate is null!"); - return response; - } - SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); - Date date = formatter.parse(strDate); - long timeStamp = date.getTime(); - BRSharedPrefs.putSecureTime(app, timeStamp); - } catch (ParseException | IOException e) { - Timber.e(e); - } finally { - if (resp != null) resp.close(); - } - return response; - } - @Retention(RetentionPolicy.SOURCE) @StringDef({LUXURY, REGULAR, ECONOMY}) public @interface FeeType { diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/SettingsState.kt b/app/src/main/java/com/brainwallet/ui/screens/home/SettingsState.kt index 9f924c3c..60a209bd 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/home/SettingsState.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/home/SettingsState.kt @@ -1,6 +1,10 @@ package com.brainwallet.ui.screens.home + import com.brainwallet.data.model.CurrencyEntity +import com.brainwallet.data.model.Fee +import com.brainwallet.data.model.FeeOption import com.brainwallet.data.model.Language +import com.brainwallet.data.model.toFeeOptions data class SettingsState( val darkMode: Boolean = true, @@ -15,4 +19,5 @@ data class SettingsState( val fiatSelectorBottomSheetVisible: Boolean = false, val shareAnalyticsDataEnabled: Boolean = false, val lastSyncMetadata: String? = null, + val currentFeeOptions: List = Fee.Default.toFeeOptions(), ) \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/SettingsViewModel.kt b/app/src/main/java/com/brainwallet/ui/screens/home/SettingsViewModel.kt index e9515ce8..8859d395 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/home/SettingsViewModel.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/home/SettingsViewModel.kt @@ -5,6 +5,8 @@ import androidx.core.os.LocaleListCompat import androidx.lifecycle.viewModelScope import com.brainwallet.data.model.AppSetting import com.brainwallet.data.model.Language +import com.brainwallet.data.model.toFeeOptions +import com.brainwallet.data.repository.LtcRepository import com.brainwallet.data.repository.SettingRepository import com.brainwallet.ui.BrainwalletViewModel import com.brainwallet.util.EventBus @@ -21,7 +23,8 @@ import kotlinx.coroutines.launch class SettingsViewModel( - private val settingRepository: SettingRepository + private val settingRepository: SettingRepository, + private val ltcRepository: LtcRepository ) : BrainwalletViewModel() { private val _state = MutableStateFlow(SettingsState()) @@ -50,7 +53,8 @@ class SettingsViewModel( _state.update { it.copy( shareAnalyticsDataEnabled = event.shareAnalyticsDataEnabled, - lastSyncMetadata = event.lastSyncMetadata + lastSyncMetadata = event.lastSyncMetadata, + currentFeeOptions = ltcRepository.fetchFeePerKb().toFeeOptions() ) } } diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/composable/HomeSettingDrawerSheet.kt b/app/src/main/java/com/brainwallet/ui/screens/home/composable/HomeSettingDrawerSheet.kt index 42b370a8..5c0c6a9c 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/home/composable/HomeSettingDrawerSheet.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/home/composable/HomeSettingDrawerSheet.kt @@ -60,7 +60,7 @@ fun HomeSettingDrawerSheet( LaunchedEffect(Unit) { viewModel.onEvent(SettingsEvent.OnLoad( shareAnalyticsDataEnabled = BRSharedPrefs.getShareData(context), //currently just load analytics share data here - lastSyncMetadata = BRSharedPrefs.getSyncMetadata(context) //currently just load sync metadata here + lastSyncMetadata = BRSharedPrefs.getSyncMetadata(context), //currently just load sync metadata here )) } @@ -134,6 +134,8 @@ fun HomeSettingDrawerSheet( modifier = Modifier .fillMaxSize() .wrapContentHeight(), + selectedCurrency = state.selectedCurrency, + feeOptions = state.currentFeeOptions, onEvent = { viewModel.onEvent(it) } diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LitecoinBlockchainDetail.kt b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LitecoinBlockchainDetail.kt index 339584cd..138ab31c 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LitecoinBlockchainDetail.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LitecoinBlockchainDetail.kt @@ -1,26 +1,50 @@ package com.brainwallet.ui.screens.home.composable.settingsrows +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SegmentedButton +import androidx.compose.material3.SegmentedButtonDefaults +import androidx.compose.material3.SingleChoiceSegmentedButtonRow import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import com.brainwallet.R +import com.brainwallet.data.model.CurrencyEntity +import com.brainwallet.data.model.Fee +import com.brainwallet.data.model.FeeOption +import com.brainwallet.data.model.getFiatFormatted +import com.brainwallet.data.model.toFeeOptions +import com.brainwallet.tools.manager.FeeManager import com.brainwallet.ui.screens.home.SettingsEvent +import com.brainwallet.ui.theme.BrainwalletTheme +import com.brainwallet.wallet.BRWalletManager //TODO @Composable fun LitecoinBlockchainDetail( modifier: Modifier = Modifier, + selectedCurrency: CurrencyEntity, + feeOptions: List, onEvent: (SettingsEvent) -> Unit, ) { + var feeOptionsState by remember { mutableIntStateOf(2) } //2 -> index of top, since we have [low,medium,top] + /// Layout values val contentHeight = 60 val horizontalPadding = 14 @@ -35,19 +59,89 @@ fun LitecoinBlockchainDetail( ) { Row( - modifier = Modifier - .height(contentHeight.dp), + modifier = Modifier.height(contentHeight.dp), verticalAlignment = Alignment.CenterVertically ) { - Text(stringResource(R.string.settings_blockchain_litecoin_description)) - Spacer(modifier = Modifier.weight(1f)) - Button(onClick = { - onEvent.invoke(SettingsEvent.OnBlockchainSyncClick) - }) { + Text( + text = stringResource(R.string.settings_blockchain_litecoin_description), + modifier = Modifier.weight(1.3f) + ) + Button( + modifier = Modifier.weight(.7f), + onClick = { + onEvent.invoke(SettingsEvent.OnBlockchainSyncClick) + } + ) { Text(stringResource(R.string.settings_blockchain_litecoin_button)) } } + HorizontalDivider(color = BrainwalletTheme.colors.content) + + NetworkFeeSelector( + selectedCurrency = selectedCurrency, + feeOptions = feeOptions, + selectedIndex = feeOptionsState + ) { newSelectedIndex -> + feeOptionsState = newSelectedIndex + + //just update inside BRWalletManager.setFeePerKb + BRWalletManager.getInstance().setFeePerKb(feeOptions[newSelectedIndex].feePerKb) + } + + } + } +} + +@Composable +private fun NetworkFeeSelector( + selectedCurrency: CurrencyEntity, + feeOptions: List, + selectedIndex: Int, + onSelectedChange: (Int) -> Unit +) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Text( + text = stringResource(R.string.network_fee_options_desc), + fontSize = 12.sp, + ) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + feeOptions.forEachIndexed { index, feeOption -> + Column(horizontalAlignment = Alignment.CenterHorizontally) { + Text( + text = "${feeOption.feePerKb}", + fontWeight = FontWeight.Bold + ) + Text( + text = feeOptions[index].getFiatFormatted(selectedCurrency), //fiat? + fontSize = 12.sp + ) + } + } + } + + SingleChoiceSegmentedButtonRow { + feeOptions.forEachIndexed { index, feeOption -> + SegmentedButton( + shape = SegmentedButtonDefaults.itemShape( + index = index, + count = feeOptions.size, + baseShape = MaterialTheme.shapes.extraLarge + ), + onClick = { onSelectedChange.invoke(index) }, + selected = index == selectedIndex, + label = { Text(stringResource(feeOption.labelStringId)) } + ) + } } + + } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/brainwallet/wallet/BRWalletManager.java b/app/src/main/java/com/brainwallet/wallet/BRWalletManager.java index 7a37d9cd..507a5125 100644 --- a/app/src/main/java/com/brainwallet/wallet/BRWalletManager.java +++ b/app/src/main/java/com/brainwallet/wallet/BRWalletManager.java @@ -514,9 +514,9 @@ public void initWallet(final Context ctx) { String firstAddress = BRWalletManager.getFirstAddress(pubkeyEncoded); BRSharedPrefs.putFirstAddress(ctx, firstAddress); FeeManager feeManager = FeeManager.getInstance(); - if (feeManager.isRegularFee()) { - feeManager.updateFeePerKb(ctx); - BRWalletManager.getInstance().setFeePerKb(feeManager.currentFees.regular); + if (feeManager.isLuxuryFee()) { + FeeManager.updateFeePerKb(ctx); + BRWalletManager.getInstance().setFeePerKb(feeManager.currentFeeOptions.luxury); } } diff --git a/app/src/main/res/layout/fragment_send.xml b/app/src/main/res/layout/fragment_send.xml index c60707bd..742ea48f 100644 --- a/app/src/main/res/layout/fragment_send.xml +++ b/app/src/main/res/layout/fragment_send.xml @@ -216,105 +216,15 @@ android:textSize="18sp" app:buttonType="2" app:isBreadButton="true" - app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintVertical_bias="0.0" /> - - - - - - - - - - - - - - - - - - - - + - مشاركة بيانات التحليلات تحديث الرقم السري عرض + رسوم الشبكة (لكل كيلو بايت): القيمة الأعلى تعني اكتمال المعاملة في وقت أقرب + قمة + واسطة + قليل diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 4d0e68ac..6d272928 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -796,4 +796,8 @@ Analyse-Daten teilen PIN aktualisieren Anzeigen + Netzwerkgebühr (pro KB): Ein höherer Wert bedeutet, dass die Transaktion früher abgeschlossen wird + Spitze + Medium + Niedrig diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 9f12f07d..24bf3fc0 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -169,9 +169,9 @@ Ignorar - SEGURIDAD DEL DISPOSITIVO COMPROMETIDA\nCualquier aplicación \"jailbreak\" puede acceder a los datos del llavero de Loaf y robar tus Litecoins. Borra esta cartera de inmediato y restáurala en un dispositivo seguro. + SEGURIDAD DEL DISPOSITIVO COMPROMETIDA\nCualquier aplicación "jailbreak" puede acceder a los datos del llavero de Loaf y robar tus Litecoins. Borra esta cartera de inmediato y restáurala en un dispositivo seguro. - SEGURIDAD DEL DISPOSITIVO COMPROMETIDA\nCualquier aplicación \"jailbreak\" puede acceder a los datos del llavero de Loaf y robar tus Litecoins. Usa Loaf únicamente en un dispositivo sin jailbreak. + SEGURIDAD DEL DISPOSITIVO COMPROMETIDA\nCualquier aplicación "jailbreak" puede acceder a los datos del llavero de Loaf y robar tus Litecoins. Usa Loaf únicamente en un dispositivo sin jailbreak. AVISO @@ -795,4 +795,8 @@ Compartir datos analíticos Actualizar PIN Mostrar + Tarifa de red (por kb): un valor más alto significa que la transacción se completa antes + Arriba + Medio + Bajo diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 93928b67..1571dd93 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -796,4 +796,8 @@ Partager les données analytiques Mettre à jour le code PIN Afficher + Frais de réseau (par Ko): une valeur plus élevée signifie que la transaction se termine plus tôt + Haut + Moyen + Faible diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 8a0158a5..a03d849c 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -434,4 +434,8 @@ विश्लेषण डेटा साझा करें पिन अपडेट करें दिखाएं + नेटवर्क शुल्क (प्रति केबी): उच्च मूल्य का मतलब है कि लेनदेन जल्दी पूरा हो जाएगा + शीर्ष + मध्यम + कम diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 7899cb2d..d3bb43e0 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -798,4 +798,8 @@ Bagikan data analitik Perbarui PIN Tampilkan + Biaya Jaringan (per kb): Nilai yang lebih tinggi berarti transaksi selesai lebih cepat + Atas + Sedang + Rendah diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 6641145b..592ebba1 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -796,4 +796,8 @@ Condividere i dati analitici Aggiorna PIN Mostra + Tariffa di rete (per kb): un valore più elevato significa che la transazione viene completata prima + Superiore + Medio + Basso diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 523cd7f2..c6ffb20c 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -796,4 +796,8 @@ 分析データを共有 PIN を更新 表示 + ネットワーク料金 (kb あたり): 値が高いほど、トランザクションが早く完了することを意味します + トップ + 中くらい + 低い diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 3deda254..8ec4b384 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -796,4 +796,8 @@ 분석 데이터 공유 PIN 업데이트 표시 + 네트워크 수수료(kb당): 값이 높을수록 거래가 더 빨리 완료됨을 의미합니다. + 맨 위 + 중간 + 낮은 diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 48a2dc0b..27b64935 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -795,4 +795,8 @@ Compartilhar dados analíticos Atualizar PIN Mostrar + Taxa de rede (por kb): valor mais alto significa que a transação é concluída mais cedo + Principal + Médio + Baixo diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 22df2082..4df74670 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -796,4 +796,8 @@ Делиться аналитическими данными Обновить PIN Показать + Сетевая плата (за КБ): более высокое значение означает, что транзакция завершится раньше. + Вершина + Середина + Низкий diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 12d62935..78b503fd 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -434,4 +434,8 @@ Dela analysdata Uppdatera PIN Visa + Nätverksavgift (per kb): Högre värde innebär att transaktionen slutförs tidigare + Bästa + Medium + Låg diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index d1e3c107..a526c60c 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -819,4 +819,8 @@ Analitik verileri paylaş PIN güncelle Göster + Ağ Ücreti (kb başına): Daha yüksek değer, işlemin daha erken tamamlanacağı anlamına gelir + Tepe + Orta + Düşük diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 3f7aca4a..b5d20546 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -802,4 +802,8 @@ Ділитися аналітичними даними Оновити PIN Показати + Плата за мережу (за кб): вищий показник означає, що транзакція завершується швидше + Топ + Середній + Низький diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index b25903f6..b1517637 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -764,7 +764,7 @@ 你可以从开始的地方返回 恢复我的脑钱包 清除 - 不要猜测。\n\n这将需要你 \n5,444,517,950,000,000,000,000,000,000,000,000,000,000,000,000,000 次尝试 + 不要猜测。\n\n这将需要你 \n5,444,517,950,000,000,000,000,000,000,000,000,000,000,000,000,000,000 次尝试 确认 你没有忘记吧?再次输入。或者,返回重新开始。 准备好 @@ -796,4 +796,8 @@ 分享分析数据 更新 PIN 显示 + 网络费用(每 kb):值越高意味着交易完成得越快 + 顶部 + 中等的 + 低的 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 13e6b9cc..69514c55 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -796,4 +796,8 @@ 分享分析數據 更新 PIN 顯示 + 網路費用(每 kb):數值越高代表交易完成越快 + 頂部 + 中等的 + 低的 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1b2f4e52..3e6f5bbe 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -805,7 +805,7 @@ You can get back from where you started Restore my Brainwallet Clear - Don’t guess.\n\nIt would take you \n5,444,517,950,000,000,000,000,000,000,000,000,000,000,000,000,000 tries + Don’t guess.\n\nIt would take you \n5,444,517,950,000,000,000,000,000,000,000,000,000,000,000,000,000,000 tries Confirm You didn’t forget did you? Enter it again. Or, go back to start over. Ready @@ -839,5 +839,8 @@ Share analytics data Update PIN Show - + Network Fee (per kb): Higher value mean the transaction completes sooner + Top + Medium + Low