Updated on 2026-08-14
This commit is contained in:
commit
2bb6a2b17d
28 changed files with 303 additions and 155 deletions
|
|
@ -72,12 +72,12 @@ dependencies {
|
|||
implementation 'com.google.android.material:material:1.2.1'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1'
|
||||
|
||||
implementation 'com.tangem:blockchain:1.128.0'
|
||||
implementation 'com.tangem:core:1.92.0'
|
||||
implementation 'com.tangem:sdk:1.92.0'
|
||||
implementation 'com.tangem:blockchain:1.141.0'
|
||||
implementation 'com.tangem:core:1.101.0'
|
||||
implementation 'com.tangem:sdk:1.101.0'
|
||||
|
||||
// WebView
|
||||
implementation "androidx.browser:browser:1.2.0"
|
||||
implementation "androidx.browser:browser:1.3.0"
|
||||
|
||||
//lifecycle
|
||||
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
|
||||
|
|
@ -103,7 +103,7 @@ dependencies {
|
|||
implementation 'com.google.firebase:firebase-config-ktx'
|
||||
implementation 'com.google.firebase:firebase-analytics-ktx'
|
||||
|
||||
testImplementation 'junit:junit:4.13'
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
testImplementation "com.google.truth:truth:1.0.1"
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
|
|
|
|||
|
|
@ -36,17 +36,17 @@ fun String.toQrCode(): Bitmap {
|
|||
return bmp
|
||||
}
|
||||
|
||||
fun BigDecimal.toFormattedString(decimals: Int): String {
|
||||
val symbols = DecimalFormatSymbols(Locale.US)
|
||||
symbols.decimalSeparator = '.'
|
||||
fun BigDecimal.toFormattedString(
|
||||
decimals: Int, roundingMode: RoundingMode = RoundingMode.DOWN, locale: Locale = Locale.US
|
||||
): String {
|
||||
val symbols = DecimalFormatSymbols(locale)
|
||||
val df = DecimalFormat()
|
||||
df.decimalFormatSymbols = symbols
|
||||
df.maximumFractionDigits = decimals
|
||||
df.minimumFractionDigits = 0
|
||||
df.isGroupingUsed = false
|
||||
val bd = BigDecimal(unscaledValue(), scale())
|
||||
bd.setScale(decimals, RoundingMode.DOWN)
|
||||
return df.format(bd)
|
||||
df.roundingMode = roundingMode
|
||||
return df.format(this)
|
||||
}
|
||||
|
||||
fun BigDecimal.toFormattedCurrencyString(decimals: Int, currency: String): String {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.common.redux.global
|
|||
|
||||
import com.tangem.tap.domain.config.ConfigManager
|
||||
import com.tangem.tap.domain.tasks.ScanNoteResponse
|
||||
import com.tangem.tap.features.details.redux.SecurityOption
|
||||
import org.rekotlin.Action
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
@ -17,4 +18,5 @@ sealed class GlobalAction : Action {
|
|||
}
|
||||
data class UpdateWalletSignedHashes(val walletSignedHashes: Int?) : GlobalAction()
|
||||
data class SetConfigManager(val configManager: ConfigManager) : GlobalAction()
|
||||
data class UpdateSecurityOptions(val securityOption: SecurityOption) : GlobalAction()
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.common.redux.global
|
||||
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.features.details.redux.SecurityOption
|
||||
import org.rekotlin.Action
|
||||
|
||||
fun globalReducer(action: Action, state: AppState): GlobalState {
|
||||
|
|
@ -36,6 +37,24 @@ fun globalReducer(action: Action, state: AppState): GlobalState {
|
|||
is GlobalAction.SetConfigManager -> {
|
||||
globalState.copy(configManager = action.configManager)
|
||||
}
|
||||
is GlobalAction.UpdateSecurityOptions -> {
|
||||
val card = when (action.securityOption) {
|
||||
SecurityOption.LongTap -> globalState.scanNoteResponse?.card?.copy(
|
||||
isPin1Default = true, isPin2Default = true
|
||||
)
|
||||
SecurityOption.PassCode -> globalState.scanNoteResponse?.card?.copy(
|
||||
isPin1Default = true, isPin2Default = false
|
||||
)
|
||||
SecurityOption.AccessCode -> globalState.scanNoteResponse?.card?.copy(
|
||||
isPin1Default = false, isPin2Default = true
|
||||
)
|
||||
}
|
||||
if (card != null) {
|
||||
globalState.copy(scanNoteResponse = globalState.scanNoteResponse?.copy(card = card))
|
||||
} else {
|
||||
globalState
|
||||
}
|
||||
}
|
||||
else -> globalState
|
||||
}
|
||||
}
|
||||
|
|
@ -38,6 +38,10 @@ sealed class TapError(
|
|||
object DustChange : TapError(R.string.send_error_dust_change)
|
||||
data class CreateAccountUnderfunded(override val args: List<Any>) : TapError(R.string.send_error_no_target_account)
|
||||
|
||||
sealed class XmlError {
|
||||
object AssetAccountNotCreated: TapError(R.string.send_error_no_account_xlm)
|
||||
}
|
||||
|
||||
data class ValidateTransactionErrors(
|
||||
override val errorList: List<TapError>,
|
||||
override val builder: (List<String>) -> String
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class ScanNoteTask(val card: Card? = null) : CardSessionRunnable<ScanNoteRespons
|
|||
)))
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
callback(CompletionResult.Failure(TangemSdkError.VerificationFailed()))
|
||||
callback(CompletionResult.Failure(TangemSdkError.CardVerificationFailed()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,6 +140,9 @@ class DetailsMiddleware {
|
|||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
selectedOption?.let {
|
||||
store.dispatch(GlobalAction.UpdateSecurityOptions(it))
|
||||
}
|
||||
if (selectedOption != SecurityOption.LongTap) {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,23 +144,8 @@ private fun handleSecurityAction(
|
|||
allowedOptions = EnumSet.noneOf(SecurityOption::class.java)
|
||||
))
|
||||
}
|
||||
val prohibitDefaultPin = state.card.settingsMask?.contains(Settings.ProhibitDefaultPIN1) == true
|
||||
val allowSetPin1 = state.card.settingsMask?.contains(Settings.AllowSetPIN1) != false
|
||||
val allowSetPin2 = state.card.settingsMask?.contains(Settings.AllowSetPIN2) != false
|
||||
val isDefaultPin1 = state.card.isPin1Default != false
|
||||
val isDefaultPin2 = state.card.isPin2Default != false
|
||||
|
||||
val allowedSecurityOptions = EnumSet.noneOf(SecurityOption::class.java)
|
||||
if ((isDefaultPin1 && isDefaultPin2) || !prohibitDefaultPin) {
|
||||
allowedSecurityOptions.add(SecurityOption.LongTap)
|
||||
}
|
||||
if (allowSetPin1 && (isDefaultPin2 || !prohibitDefaultPin)) {
|
||||
allowedSecurityOptions.add(SecurityOption.AccessCode)
|
||||
}
|
||||
if (allowSetPin2 && (isDefaultPin1 || !prohibitDefaultPin)) {
|
||||
allowedSecurityOptions.add(SecurityOption.PassCode)
|
||||
}
|
||||
|
||||
val allowedSecurityOptions = prepareAllowedSecurityOptions(state.card)
|
||||
state.copy(securityScreenState = state.securityScreenState?.copy(
|
||||
allowedOptions = allowedSecurityOptions,
|
||||
selectedOption = state.securityScreenState.currentOption
|
||||
|
|
@ -180,15 +165,37 @@ private fun handleSecurityAction(
|
|||
state.copy(confirmScreenState = confirmScreenState)
|
||||
}
|
||||
is DetailsAction.ManageSecurity.SaveChanges.Success -> {
|
||||
state.copy(securityScreenState = state.securityScreenState?.copy(
|
||||
currentOption = state.securityScreenState.selectedOption
|
||||
))
|
||||
// Setting options to show only LongTap from now on
|
||||
state.copy(
|
||||
card = state.card?.copy(isPin1Default = true, isPin2Default = true),
|
||||
securityScreenState = state.securityScreenState?.copy(
|
||||
currentOption = state.securityScreenState.selectedOption,
|
||||
allowedOptions = EnumSet.of(SecurityOption.LongTap)
|
||||
))
|
||||
}
|
||||
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
||||
private fun prepareAllowedSecurityOptions(card: Card): EnumSet<SecurityOption> {
|
||||
val prohibitDefaultPin = card.settingsMask?.contains(Settings.ProhibitDefaultPIN1) == true
|
||||
val isDefaultPin1 = card.isPin1Default != false
|
||||
val isDefaultPin2 = card.isPin2Default != false
|
||||
|
||||
val allowedSecurityOptions = EnumSet.noneOf(SecurityOption::class.java)
|
||||
if ((isDefaultPin1 && isDefaultPin2) || !prohibitDefaultPin) {
|
||||
allowedSecurityOptions.add(SecurityOption.LongTap)
|
||||
}
|
||||
if (!isDefaultPin1) {
|
||||
allowedSecurityOptions.add(SecurityOption.AccessCode)
|
||||
}
|
||||
if (!isDefaultPin2) {
|
||||
allowedSecurityOptions.add(SecurityOption.PassCode)
|
||||
}
|
||||
return allowedSecurityOptions
|
||||
}
|
||||
|
||||
|
||||
private fun Card.toCardInfo(): CardInfo? {
|
||||
val cardId = this.cardId.chunked(4).joinToString(separator = " ")
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import android.view.View
|
|||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.transition.TransitionInflater
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.details.redux.DetailsAction
|
||||
import com.tangem.tap.features.details.redux.DetailsState
|
||||
|
|
@ -91,6 +92,7 @@ class DetailsSecurityFragment : Fragment(R.layout.fragment_details_security),
|
|||
}
|
||||
|
||||
private fun enableLongTap(enable: Boolean) {
|
||||
group_long_tap.show(enable)
|
||||
val alpha = if (enable) 1f else 0.5f
|
||||
tv_long_tap_description.alpha = alpha
|
||||
tv_long_tap_title.alpha = alpha
|
||||
|
|
@ -105,6 +107,7 @@ class DetailsSecurityFragment : Fragment(R.layout.fragment_details_security),
|
|||
}
|
||||
|
||||
private fun enablePasscode(enable: Boolean) {
|
||||
group_passcode.show(enable)
|
||||
val alpha = if (enable) 1f else 0.5f
|
||||
tv_passcode_description.alpha = alpha
|
||||
tv_passcode_title.alpha = alpha
|
||||
|
|
@ -119,6 +122,7 @@ class DetailsSecurityFragment : Fragment(R.layout.fragment_details_security),
|
|||
}
|
||||
|
||||
private fun enableAccessCode(enable: Boolean) {
|
||||
group_access_code.show(enable)
|
||||
val alpha = if (enable) 1f else 0.5f
|
||||
tv_access_code_description.alpha = alpha
|
||||
tv_access_code_title.alpha = alpha
|
||||
|
|
|
|||
|
|
@ -98,7 +98,9 @@ class CreateTwinWalletFragment : Fragment(R.layout.fragment_details_twin_cards),
|
|||
btn_tap.setOnClickListener {
|
||||
store.dispatch(DetailsAction.CreateTwinWalletAction.LaunchFirstStep(
|
||||
Message(getString(
|
||||
R.string.details_twins_recreate_title_format, twinCardNumber)
|
||||
R.string.details_twins_recreate_title_format,
|
||||
twinCardNumberString
|
||||
)
|
||||
)))
|
||||
}
|
||||
btn_tap.text = getString(R.string.details_twins_recreate_button_format,
|
||||
|
|
|
|||
|
|
@ -110,7 +110,24 @@ internal class AddressPayIdMiddleware {
|
|||
}
|
||||
|
||||
private fun verifyAddress(address: String, wallet: Wallet, isUserInput: Boolean, dispatch: (Action) -> Unit) {
|
||||
val supposedAddress = extractAddressFromShareUri(address).removeNonAddressData()
|
||||
val addressSchemeSplit = address.split(":")
|
||||
val noSchemeAddress = when (addressSchemeSplit.size) {
|
||||
1 -> address // no scheme
|
||||
2 -> { // scheme
|
||||
if (wallet.blockchain.validateShareScheme(addressSchemeSplit[0])) {
|
||||
addressSchemeSplit[1]
|
||||
} else {
|
||||
dispatch(SetAddressError(Error.ADDRESS_INVALID_OR_UNSUPPORTED_BY_BLOCKCHAIN))
|
||||
return
|
||||
}
|
||||
}
|
||||
else -> { // invalid URI
|
||||
dispatch(SetAddressError(Error.ADDRESS_INVALID_OR_UNSUPPORTED_BY_BLOCKCHAIN))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val supposedAddress = noSchemeAddress.removeShareUriQuery() //TODO: parse query?
|
||||
|
||||
val failReason = isValidBlockchainAddressAndNotTheSameAsWallet(wallet, supposedAddress)
|
||||
if (failReason == null) {
|
||||
|
|
@ -141,7 +158,7 @@ internal class AddressPayIdMiddleware {
|
|||
return if (prefixes.isEmpty()) shareUri else shareUri.replace(prefixes[0], "")
|
||||
}
|
||||
|
||||
private fun String.removeNonAddressData(): String = this.substringBefore("?")
|
||||
private fun String.removeShareUriQuery(): String = this.substringBefore("?")
|
||||
|
||||
private fun verifyClipboard(input: String?, appState: AppState?, dispatch: DispatchFunction) {
|
||||
val addressPayId = input ?: return
|
||||
|
|
|
|||
|
|
@ -140,6 +140,11 @@ private fun sendTransaction(
|
|||
message.contains("50002") -> {
|
||||
// user was cancelled the operation by closing the Sdk bottom sheet
|
||||
}
|
||||
// make it easier latter by handling an appropriate enumError or, like on iOS,
|
||||
// accept a string identifier of the error message
|
||||
message.contains("Target account is not created. To create account send 1+ XLM.")-> {
|
||||
dispatch(SendAction.SendError(TapError.XmlError.AssetAccountNotCreated))
|
||||
}
|
||||
else -> {
|
||||
Timber.e(throwable)
|
||||
FirebaseCrashlytics.getInstance().recordException(throwable)
|
||||
|
|
|
|||
|
|
@ -24,8 +24,9 @@ class TransactionExtrasReducer : SendInternalReducer {
|
|||
val emptyResult = TransactionExtrasState()
|
||||
val result = when (action.blockchain) {
|
||||
Blockchain.XRP -> {
|
||||
val address = action.walletAddress.substringAfter(":")
|
||||
// 'r' - without tag, 'x' - with tag
|
||||
if (action.walletAddress.startsWith("r", true)) {
|
||||
if (address.startsWith("r", true)) {
|
||||
val tag = action.xrpTag?.toLongOrNull()
|
||||
if (tag == null) {
|
||||
TransactionExtrasState(xrpDestinationTag = XrpDestinationTagState())
|
||||
|
|
@ -54,7 +55,7 @@ class TransactionExtrasReducer : SendInternalReducer {
|
|||
sendState: SendState,
|
||||
infoState: TransactionExtrasState,
|
||||
): SendState {
|
||||
fun clearMemo(memo: XlmMemoState): XlmMemoState = memo.copy(text = null, id = null)
|
||||
fun clearMemo(memo: XlmMemoState): XlmMemoState = memo.copy(text = null, id = null, error = null)
|
||||
|
||||
val result = when (action) {
|
||||
// is XlmMemo.ChangeSelectedMemo -> {
|
||||
|
|
@ -68,13 +69,22 @@ class TransactionExtrasReducer : SendInternalReducer {
|
|||
// }
|
||||
is XlmMemo.HandleUserInput -> {
|
||||
val inputViewValue = InputViewValue(action.data, true)
|
||||
var memo = infoState.xlmMemo?.copy(viewFieldValue = inputViewValue) ?: XlmMemoState(inputViewValue)
|
||||
var memo = infoState.xlmMemo?.copy(viewFieldValue = inputViewValue)
|
||||
?: XlmMemoState(inputViewValue)
|
||||
memo = clearMemo(memo)
|
||||
memo = when (infoState.xlmMemo?.selectedMemoType) {
|
||||
XlmMemoType.TEXT -> memo.copy(text = StellarMemo.Text(action.data))
|
||||
XlmMemoType.ID -> {
|
||||
val id = action.data.toIntOrNull()?.toBigInteger()
|
||||
if (id != null) memo.copy(id = StellarMemo.Id(id)) else memo
|
||||
val id = action.data.toBigIntegerOrNull()
|
||||
if (id != null) {
|
||||
if (id > XlmMemoState.MAX_NUMBER) {
|
||||
memo.copy(error = TransactionExtraError.INVALID_XLM_MEMO)
|
||||
} else {
|
||||
memo.copy(id = StellarMemo.Id(id))
|
||||
}
|
||||
} else {
|
||||
memo
|
||||
}
|
||||
}
|
||||
null -> memo
|
||||
}
|
||||
|
|
@ -93,7 +103,12 @@ class TransactionExtrasReducer : SendInternalReducer {
|
|||
is XrpDestinationTag.HandleUserInput -> {
|
||||
val tag = action.data.toLongOrNull()
|
||||
if (tag != null) {
|
||||
val tagState = XrpDestinationTagState(InputViewValue(action.data, true), tag)
|
||||
val input = InputViewValue(action.data, true)
|
||||
val tagState = if (tag <= XrpDestinationTagState.MAX_NUMBER){
|
||||
XrpDestinationTagState(input, tag)
|
||||
} else {
|
||||
XrpDestinationTagState(input, error = TransactionExtraError.INVALID_DESTINATION_TAG)
|
||||
}
|
||||
infoState.copy(xrpDestinationTag = tagState)
|
||||
} else {
|
||||
infoState
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.features.send.redux.states
|
|||
|
||||
import com.tangem.blockchain.blockchains.stellar.StellarMemo
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction
|
||||
import java.math.BigInteger
|
||||
|
||||
data class AddressPayIdState(
|
||||
val viewFieldValue: InputViewValue = InputViewValue(""),
|
||||
|
|
@ -39,16 +40,31 @@ data class XlmMemoState(
|
|||
val selectedMemoType: XlmMemoType = XlmMemoType.ID,
|
||||
val text: StellarMemo.Text? = null,
|
||||
val id: StellarMemo.Id? = null,
|
||||
val error: TransactionExtraError? = null,
|
||||
) {
|
||||
val memo: StellarMemo?
|
||||
get() = when (selectedMemoType) {
|
||||
XlmMemoType.TEXT -> text
|
||||
XlmMemoType.ID -> id
|
||||
}
|
||||
|
||||
companion object {
|
||||
val MAX_NUMBER: BigInteger = BigInteger("FFFFFFFFFFFFFFFF", 16)
|
||||
}
|
||||
}
|
||||
|
||||
// tag must contains only digits
|
||||
data class XrpDestinationTagState(
|
||||
val viewFieldValue: InputViewValue = InputViewValue(""),
|
||||
val tag: Long? = null
|
||||
)
|
||||
val tag: Long? = null,
|
||||
val error: TransactionExtraError? = null
|
||||
) {
|
||||
companion object {
|
||||
const val MAX_NUMBER: Long = 4294967295
|
||||
}
|
||||
}
|
||||
|
||||
enum class TransactionExtraError {
|
||||
INVALID_DESTINATION_TAG,
|
||||
INVALID_XLM_MEMO
|
||||
}
|
||||
|
|
@ -70,9 +70,25 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
|
|||
XlmMemoType.ID -> InputType.TYPE_CLASS_NUMBER
|
||||
}
|
||||
if (!it.viewFieldValue.isFromUserInput) fg.etMemo.setText(it.viewFieldValue.value)
|
||||
if (it.error != null) {
|
||||
if (it.error == TransactionExtraError.INVALID_XLM_MEMO) {
|
||||
fg.tilMemo.error = fg.getText(R.string.send_error_invalid_memo_id)
|
||||
}
|
||||
} else {
|
||||
fg.tilMemo.error = null
|
||||
}
|
||||
}
|
||||
infoState.xrpDestinationTag?.let {
|
||||
if (!it.viewFieldValue.isFromUserInput) fg.etDestinationTag.setText(it.viewFieldValue.value)
|
||||
if (infoState.xrpDestinationTag.error != null) {
|
||||
if (infoState.xrpDestinationTag.error == TransactionExtraError.INVALID_DESTINATION_TAG) {
|
||||
fg.tilDestinationTag.error = fg.getText(R.string.send_error_invalid_destination_tag)
|
||||
}
|
||||
} else {
|
||||
fg.tilDestinationTag.error = null
|
||||
}
|
||||
if (!it.viewFieldValue.isFromUserInput) {
|
||||
fg.etDestinationTag.setText(it.viewFieldValue.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,11 +32,13 @@ data class WalletState(
|
|||
currencyData.status != com.tangem.tap.features.wallet.ui.BalanceStatus.EmptyCard &&
|
||||
currencyData.status != com.tangem.tap.features.wallet.ui.BalanceStatus.UnknownBlockchain
|
||||
|
||||
val showSegwitAddress: Boolean
|
||||
val showMultipleAddress: Boolean
|
||||
get() {
|
||||
val listOfAddresses = walletAddresses?.list ?: return false
|
||||
return (wallet?.blockchain == Blockchain.Bitcoin || wallet?.blockchain == Blockchain.BitcoinTestnet)
|
||||
&& listOfAddresses.size > 1
|
||||
return (wallet?.blockchain == Blockchain.Bitcoin ||
|
||||
wallet?.blockchain == Blockchain.BitcoinTestnet ||
|
||||
wallet?.blockchain == Blockchain.CardanoShelley) &&
|
||||
listOfAddresses.size > 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import androidx.transition.TransitionInflater
|
|||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.tangem.blockchain.blockchains.bitcoin.BitcoinAddressType
|
||||
import com.tangem.blockchain.blockchains.cardano.CardanoAddressType
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.address.AddressType
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
|
|
@ -228,28 +230,23 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
private fun setupAddressCard(state: WalletState) {
|
||||
if (state.walletAddresses != null) {
|
||||
l_address?.show()
|
||||
val tvAddressPaddingTop = tv_address.resources.getDimension(R.dimen.dimen16).toInt()
|
||||
if (state.showSegwitAddress) {
|
||||
if (state.showMultipleAddress) {
|
||||
(l_address as? ViewGroup)?.beginDelayedTransition()
|
||||
tv_address.setPadding(tv_address.paddingStart, tvAddressPaddingTop / 2,
|
||||
tv_address.paddingEnd, tv_address.paddingBottom)
|
||||
chip_group_segwit.show()
|
||||
chip_group_segwit.fitChipsByGroupWidth()
|
||||
chip_group_address_type.show()
|
||||
chip_group_address_type.fitChipsByGroupWidth()
|
||||
|
||||
val checkedId = SegwitUiHelper.typeToId(state.walletAddresses.selectedAddress.type)
|
||||
if (checkedId != View.NO_ID) chip_group_segwit.check(checkedId)
|
||||
val checkedId = MultipleAddressUiHelper.typeToId(state.walletAddresses.selectedAddress.type)
|
||||
if (checkedId != View.NO_ID) chip_group_address_type.check(checkedId)
|
||||
|
||||
chip_group_segwit.setOnCheckedChangeListener { group, checkedId ->
|
||||
chip_group_address_type.setOnCheckedChangeListener { group, checkedId ->
|
||||
if (checkedId == -1) return@setOnCheckedChangeListener
|
||||
|
||||
SegwitUiHelper.idToType(checkedId)?.let {
|
||||
MultipleAddressUiHelper.idToType(checkedId, state.wallet?.blockchain)?.let {
|
||||
store.dispatch(WalletAction.ChangeSelectedAddress(it))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tv_address.setPadding(tv_address.paddingStart, tvAddressPaddingTop,
|
||||
tv_address.paddingEnd, tv_address.paddingBottom)
|
||||
chip_group_segwit.hide()
|
||||
chip_group_address_type.hide()
|
||||
}
|
||||
tv_address.text = state.walletAddresses.selectedAddress.address
|
||||
tv_explore?.setOnClickListener {
|
||||
|
|
@ -332,20 +329,34 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
|
||||
}
|
||||
|
||||
class SegwitUiHelper {
|
||||
class MultipleAddressUiHelper {
|
||||
companion object {
|
||||
fun typeToId(type: AddressType): Int {
|
||||
return when (type) {
|
||||
is BitcoinAddressType.Legacy -> R.id.chip_legacy
|
||||
is BitcoinAddressType.Segwit -> R.id.chip_default
|
||||
is CardanoAddressType.Byron -> R.id.chip_legacy
|
||||
is CardanoAddressType.Shelley -> R.id.chip_default
|
||||
else -> View.NO_ID
|
||||
}
|
||||
}
|
||||
|
||||
fun idToType(id: Int): AddressType? {
|
||||
fun idToType(id: Int, blockchain: Blockchain?): AddressType? {
|
||||
return when (id) {
|
||||
R.id.chip_default -> BitcoinAddressType.Segwit
|
||||
R.id.chip_legacy -> BitcoinAddressType.Legacy
|
||||
R.id.chip_default -> {
|
||||
when (blockchain) {
|
||||
Blockchain.Bitcoin -> BitcoinAddressType.Segwit
|
||||
Blockchain.CardanoShelley -> CardanoAddressType.Shelley
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
R.id.chip_legacy -> {
|
||||
when (blockchain) {
|
||||
Blockchain.Bitcoin -> BitcoinAddressType.Legacy
|
||||
Blockchain.CardanoShelley -> CardanoAddressType.Byron
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,154 +20,168 @@
|
|||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:title="@string/details_row_title_manage_security"
|
||||
app:navigationIcon="@drawable/ic_baseline_arrow_back_24" />
|
||||
app:navigationIcon="@drawable/ic_baseline_arrow_back_24"
|
||||
app:title="@string/details_row_title_manage_security" />
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/cl_details_confirm"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="33dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="33dp"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_long_tap"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="tv_long_tap_title, radiobutton_long_tap, tv_long_tap_description, v_long_tap" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_long_tap_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@string/details_manage_security_long_tap"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/radiobutton_long_tap"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_long_tap_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingEnd="60dp"
|
||||
android:textColor="@color/darkGray1"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_long_tap_title"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@string/details_manage_security_long_tap_description"
|
||||
android:textColor="@color/darkGray1"
|
||||
android:textSize="13sp"
|
||||
/>
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_long_tap_title" />
|
||||
|
||||
<View
|
||||
android:id="@+id/v_long_tap"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_long_tap_title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_long_tap_description"/>
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_long_tap_description"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_long_tap_title" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_passcode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="tv_passcode_title, radiobutton_passcode, tv_passcode_description, v_passcode" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_passcode_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/v_long_tap"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@string/details_manage_security_passcode"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
app:layout_constraintTop_toBottomOf="@id/v_long_tap" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/radiobutton_passcode"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/v_passcode"/>
|
||||
app:layout_constraintTop_toTopOf="@id/v_passcode" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_passcode_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingEnd="60dp"
|
||||
android:textColor="@color/darkGray1"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_passcode_title"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@string/details_manage_security_passcode_description"
|
||||
android:textColor="@color/darkGray1"
|
||||
android:textSize="13sp"
|
||||
/>
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_passcode_title" />
|
||||
|
||||
<View
|
||||
android:id="@+id/v_passcode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_passcode_title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_passcode_description"/>
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_passcode_description"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_passcode_title" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_access_code"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="tv_access_code_title, radiobutton_access_code, tv_access_code_description, v_access_code" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_access_code_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/v_passcode"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@string/details_manage_security_access_code"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
app:layout_constraintTop_toBottomOf="@id/v_passcode" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/radiobutton_access_code"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/v_access_code"/>
|
||||
app:layout_constraintTop_toTopOf="@id/v_access_code" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_access_code_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingEnd="60dp"
|
||||
android:textColor="@color/darkGray1"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_access_code_title"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@string/details_manage_security_access_code_description"
|
||||
android:textColor="@color/darkGray1"
|
||||
android:textSize="13sp"
|
||||
/>
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_access_code_title" />
|
||||
|
||||
<View
|
||||
android:id="@+id/v_access_code"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_access_code_title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_access_code_description"/>
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_access_code_description"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_access_code_title" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline"
|
||||
|
|
@ -187,9 +201,9 @@
|
|||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/common_continue"
|
||||
app:icon="@drawable/ic_save"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
|
|||
|
|
@ -43,8 +43,7 @@
|
|||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/cl_wallet"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="33dp">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_card"
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/chip_group_segwit"
|
||||
android:id="@+id/chip_group_address_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
|
|
@ -60,14 +60,13 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:ellipsize="middle"
|
||||
android:paddingStart="@dimen/dimen16"
|
||||
android:paddingTop="@dimen/dimen16"
|
||||
android:paddingEnd="@dimen/dimen16"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/darkGray1"
|
||||
android:textSize="13sp"
|
||||
app:layout_constraintEnd_toStartOf="@id/btn_copy"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/chip_group_segwit"
|
||||
app:layout_constraintTop_toTopOf="@id/btn_copy"
|
||||
tools:text="139mrsJgyWnJ**** **** y9BV" />
|
||||
|
||||
<TextView
|
||||
|
|
@ -78,14 +77,13 @@
|
|||
android:paddingStart="16dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="25dp"
|
||||
android:text="@string/wallet_address_button_explore"
|
||||
android:textColor="@color/darkGray6"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:drawableEndCompat="@drawable/ic_angle_bracket_right"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_address" />
|
||||
app:layout_constraintBottom_toBottomOf="@id/btn_copy"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
|
||||
<FrameLayout
|
||||
|
|
@ -94,12 +92,15 @@
|
|||
android:layout_height="@dimen/btn_rounded_size"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="25dp"
|
||||
android:background="@drawable/shape_ellipse"
|
||||
android:clickable="true"
|
||||
android:elevation="3dp"
|
||||
android:focusable="true"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/btn_show_qr"
|
||||
app:layout_constraintTop_toBottomOf="@id/chip_group_segwit">
|
||||
app:layout_constraintTop_toBottomOf="@id/chip_group_address_type">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_copy"
|
||||
|
|
@ -123,7 +124,7 @@
|
|||
android:elevation="3dp"
|
||||
android:focusable="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/chip_group_segwit">
|
||||
app:layout_constraintTop_toBottomOf="@id/chip_group_address_type">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_qr"
|
||||
|
|
@ -143,7 +144,8 @@
|
|||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="@color/lightGray5"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_explore" />
|
||||
android:layout_marginTop="25dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/btn_copy" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_payid_icon"
|
||||
|
|
@ -151,9 +153,9 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@drawable/ic_payid"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/v_payid_divider"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
app:layout_constraintTop_toBottomOf="@id/v_payid_divider" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_create_payid"
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/btn_top_up"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintVertical_bias="1" />
|
||||
app:layout_constraintVertical_bias="1"
|
||||
android:layout_marginBottom="33dp"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_top_up"
|
||||
|
|
@ -34,7 +35,8 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/btn_confirm_short"
|
||||
app:layout_constraintStart_toEndOf="@+id/btn_scan_short"
|
||||
app:layout_constraintVertical_bias="1" />
|
||||
app:layout_constraintVertical_bias="1"
|
||||
android:layout_marginBottom="33dp"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_confirm_short"
|
||||
|
|
@ -50,6 +52,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/btn_top_up"
|
||||
app:layout_constraintVertical_bias="1" />
|
||||
app:layout_constraintVertical_bias="1"
|
||||
android:layout_marginBottom="33dp"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -73,6 +73,7 @@
|
|||
<string name="send_total_subtitle_asset_format">%s %s und %s %s werden gesendet</string>
|
||||
<string name="send_balance_subtitle_format">Bilanz: %s %s</string>
|
||||
<string name="send_transaction_success">Die Transaktion wurde erfolgreich signiert und an den Blockchain-Knoten gesendet. Die Walletbilanz wird aktualisiert</string>
|
||||
<string name="send_error_no_account_xlm">Um ein Konto zu erstellen, senden Sie 1+ XLM an diese Adresse</string>
|
||||
<string name="details_title">Details</string>
|
||||
<string name="details_row_title_cid">KartenID</string>
|
||||
<string name="details_row_title_issuer">Emittent</string>
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
<string name="send_total_subtitle_asset_format">Sera envoyé %s %s et %s %s</string>
|
||||
<string name="send_balance_subtitle_format">Solde : %s %s</string>
|
||||
<string name="send_transaction_success">La transaction a été signée avec succès et envoyée au nœud de blockchain. Le solde du portefeuille sera mis à jour après un certain temps </string>
|
||||
<string name="send_error_no_account_xlm">Pour créer un compte, envoyez 1+ XLM à cette adresse</string>
|
||||
<string name="details_title">Référénces </string>
|
||||
<string name="details_row_title_cid">ID de la carte </string>
|
||||
<string name="details_row_title_issuer">Emetteur </string>
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@
|
|||
<string name="common_camera_denied_alert_message">Non hai fornito l\'accesso alla tua videocamera, modifica le tue impostazioni sulla privacy</string>
|
||||
<string name="common_camera_alert_button_settings">Impostazioni</string>
|
||||
<string name="home_welcome">Benvenuti in Tangem. Hai una delle nostre schede?</string>>
|
||||
<string name="home_welcome_back">Benevenuti di nuovo su Tangem Tap. Scansiona la tua scheda per iniziare.</string>
|
||||
<string name="home_button_yes">Si! Scansiona scheda.</string>
|
||||
<string name="home_welcome_back">Benevenuti di nuovo su Tangem Tap. Scansiona la tua carta per iniziare.</string>
|
||||
<string name="home_button_yes">Si! Scansiona carta.</string>
|
||||
<string name="home_button_shop">Shop</string>
|
||||
<string name="home_ready_title">Preparati ad avvicinare la tua scheda sul retro del telefono.</string>
|
||||
<string name="home_ready_title">Preparati ad avvicinare la tua carta sul retro del telefono.</string>
|
||||
<string name="home_button_tapin">Avvicina</string>
|
||||
<string name="home_button_scan">Scansiona scheda</string>
|
||||
<string name="home_button_scan">Scansiona carta</string>
|
||||
<string name="wallet_button_scan">Scansiona</string>
|
||||
<string name="wallet_button_send">Invia</string>
|
||||
<string name="wallet_button_create_wallet">Crea portafoglio</string>
|
||||
|
|
@ -29,10 +29,10 @@
|
|||
<string name="wallet_balance_blockchain_unreachable">Blockchain non raggiungibile</string>
|
||||
<string name="wallet_error_no_account">Conto non creato</string>
|
||||
<string name="wallet_error_no_account_subtitle_format">Carica %1$s+ %2$s per creare un conto</string>
|
||||
<string name="wallet_error_empty_card">Scheda vuota</string>
|
||||
<string name="wallet_error_empty_card_subtitle">Crea un portafoglio per iniziare ad utilizzare la tua scheda Tangem </string>
|
||||
<string name="wallet_error_unsupported_blockchain">Questa scheda non è supportata</string>
|
||||
<string name="wallet_error_unsupported_blockchain_subtitle"> La tua scheda Tangem è stata creata per funzionare con un\'altra applicazione. Leggere il nome e le istruzioni sulla scheda e installare l\'applicazione corretta</string>
|
||||
<string name="wallet_error_empty_card">Carta vuota</string>
|
||||
<string name="wallet_error_empty_card_subtitle">Crea un portafoglio per iniziare ad utilizzare la tua carta Tangem </string>
|
||||
<string name="wallet_error_unsupported_blockchain">Questa carta non è supportata</string>
|
||||
<string name="wallet_error_unsupported_blockchain_subtitle"> La tua carta Tangem è stata creata per funzionare con un\'altra applicazione. Leggere il nome e le istruzioni sulla carta e installare l\'applicazione corretta</string>
|
||||
<string name="wallet_balance_tx_in_progress">Transazione in corso…</string>
|
||||
<string name="wallet_pending_tx_sending">Invia\u0020</string>
|
||||
<string name="wallet_pending_tx_sending_address_format"> su %s </string>
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
<string name="wallet_address_button_create_payid">Crea PayString</string>
|
||||
<string name="wallet_qr_title_format">portafoglio %s</string>
|
||||
<string name="wallet_create_payid">Crea PayString</string>
|
||||
<string name="wallet_create_payid_card_format">Scheda: %s</string>
|
||||
<string name="wallet_create_payid_card_format">Carta: %s</string>
|
||||
<string name="wallet_create_payid_hint">Nome PayString</string>
|
||||
<string name="wallet_create_payid_domain">$payid.tangem.com</string>
|
||||
<string name="wallet_create_payid_button_title">Crea</string>
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
<string name="send_destination_hint_address_payid">Indirizzo o PayString</string>
|
||||
<string name="send_destination_hint_address">Indirizzo</string>
|
||||
<string name="send_title">Invia</string>
|
||||
<string name="send_network_fee_title">Rete libera</string>
|
||||
<string name="send_network_fee_title">Costi della rete</string>
|
||||
<string name="send_amount_label">Importo</string>
|
||||
<string name="send_fee_label">Commissione</string>
|
||||
<string name="send_total_label">Totale</string>
|
||||
|
|
@ -71,33 +71,34 @@
|
|||
<string name="send_total_subtitle_asset_format">Sarà inviato %1$s %2$s e %1$s %2$s</string>
|
||||
<string name="send_balance_subtitle_format">Saldo: %1$s %2$s</string>
|
||||
<string name="send_transaction_success">La transazione è stata firmata con successo e inviata al nodo blockchain. Il saldo del portafoglio verrà aggiornato dopo un po\' di tempo </string>
|
||||
<string name="send_error_no_account_xlm">Per creare un account, invia 1+ XLM a questo indirizzo</string>
|
||||
<string name="details_title">Requisiti</string>
|
||||
<string name="details_row_title_cid">ID scheda</string>
|
||||
<string name="details_row_title_cid">ID carta</string>
|
||||
<string name="details_row_title_issuer">Emittente</string>
|
||||
<string name="details_row_title_signed_hashes">Firmato</string>
|
||||
<string name="details_row_subtitle_signed_hashes_format">Hash %s</string>
|
||||
<string name="details_row_title_currency">Valuta dell\'applicazione</string>
|
||||
<string name="details_section_title_settings">Impostazioni</string>
|
||||
<string name="details_section_title_card">Scheda</string>
|
||||
<string name="details_row_title_validate">Convalidare la scheda</string>
|
||||
<string name="details_section_title_card">Carta</string>
|
||||
<string name="details_row_title_validate">Convalidare la carta</string>
|
||||
<string name="details_row_title_manage_security">Gestione del portafoglio</string>
|
||||
<string name="details_row_title_erase_wallet">Cancella il portafoglio</string>
|
||||
<string name="details_erase_wallet_warning">Questa azione è irreversibile. Se dopo aver eliminato il portafoglio qualcuno invia dei fondi, non potrai ritirarli.</string>
|
||||
<string name="details_security_management_warning">Se dimentichi il codice, perderai la possibilità di utilizzare la scheda. Non è possibile in alcun modo ripristinare o modificare il codice se lo perdi.</string>
|
||||
<string name="details_security_management_warning">Se dimentichi il codice, perderai la possibilità di utilizzare la carta. Non è possibile in alcun modo ripristinare o modificare il codice se lo perdi.</string>
|
||||
<string name="details_manage_security_title">Gestione della sicurezza</string>
|
||||
<string name="details_manage_security_long_tap">Mantenimento della scheda</string>
|
||||
<string name="details_manage_security_long_tap_description">Questo meccanismo protegge dagli avvicinamenti senza contatto sulla scheda. Attiva un ritardo tra la ricezione e l\'esecuzione di un comando. Dopo la prima transazione firmata, questo telefono verrà associato alla scheda e le transazioni verranno firmate immediatamente.</string>
|
||||
<string name="details_manage_security_long_tap">Mantenimento della carta</string>
|
||||
<string name="details_manage_security_long_tap_description">Questo meccanismo protegge dagli avvicinamenti senza contatto sulla carta. Attiva un ritardo tra la ricezione e l\'esecuzione di un comando. Dopo la prima transazione firmata, questo telefono verrà associato alla carta e le transazioni verranno firmate immediatamente.</string>
|
||||
<string name="details_manage_security_passcode">Password</string>
|
||||
<string name="details_manage_security_passcode_description">Dovrai inserire una password prima di eseguire qualsiasi comando che modifichi lo stato della scheda.</string>
|
||||
<string name="details_manage_security_passcode_description">Dovrai inserire una password prima di eseguire qualsiasi comando che modifichi lo stato della carta.</string>
|
||||
<string name="details_manage_security_access_code">Codice di accesso</string>
|
||||
<string name="details_manage_security_access_code_description">Prima di scansionare la scheda sarà necessario inserire il codice di accesso corretto</string>
|
||||
<string name="details_manage_security_access_code_description">Prima di scansionare la carta sarà necessario inserire il codice di accesso corretto</string>
|
||||
<string name="alert_old_device_this_card">Potresti riscontrare problemi con l\'NFC su alcuni iPhone 7/7 + durante la rimozione</string>
|
||||
<string name="alert_card_signed_transactions">Attenzione: questa scheda è già stata ricaricata e ha firmato transazioni in passato. Valuta la possibilità di prelevare immediatamente tutti i fondi se hai ricevuto questa scheda da una fonte inaffidabile.</string>
|
||||
<string name="alert_unsupported_card">Questa scheda non è progettata per funzionare con Tangem Tap</string>
|
||||
<string name="alert_developer_card">La scheda che hai scansionato è una scheda di sviluppo. Non utilizzarla come strumento di pagamento</string>
|
||||
<string name="alert_card_signed_transactions">Attenzione: questa carta è già stata ricaricata e ha firmato transazioni in passato. Valuta la possibilità di prelevare immediatamente tutti i fondi se hai ricevuto questa carta da una fonte inaffidabile.</string>
|
||||
<string name="alert_unsupported_card">Questa carta non è progettata per funzionare con Tangem Tap</string>
|
||||
<string name="alert_developer_card">La carta che hai scansionato è una carta di sviluppo. Non utilizzarla come strumento di pagamento</string>
|
||||
<string name="alert_old_card">Le schede emesse prima di settembre 2019 non possono attualmente essere utilizzate con un iPhone. Stiamo lavorando a stretto contatto con Apple per renderle disponibili nelle future versioni di iOS. </string>
|
||||
<string name="initial_message_sign_header">Avvicina per firmare</string>
|
||||
<string name="initial_message_sign_body">Avvicina la scheda al telefono come mostrato sopra </string>
|
||||
<string name="initial_message_sign_body">Avvicina la carta al telefono come mostrato sopra </string>
|
||||
<string name="initial_message_purge_wallet_body">Avvicina per cancellare il portafoglio</string>
|
||||
<string name="initial_message_create_wallet_body">Avvicina per creare il portafoglio</string>
|
||||
<string name="initial_message_change_access_code_body">Avvicina per modificare il codice di accesso</string>
|
||||
|
|
@ -161,7 +162,7 @@ Questa nota legale è stata modificata l\'ultima volta 01.10.2020.
|
|||
<string name="send_error_no_target_account">Per creare un account, invia %1$s %2$s a questo indirizzo</string>
|
||||
<string name="send_error_fee_request_failed">Impossibile ottenere la commissione</string>
|
||||
<string name="common_accept">Accetta</string>
|
||||
<string name="send_validation_amount_exceeds_balance">Amount Exceeds Balance</string>
|
||||
<string name="send_validation_amount_exceeds_balance">L\'importo supera il saldo</string>
|
||||
<string name="disclaimer_title">Termini del servizio</string>
|
||||
<string name="wallet_notification_no_internet">Nessuna connessione a Internet</string>
|
||||
|
||||
|
|
@ -184,7 +185,7 @@ Questa nota legale è stata modificata l\'ultima volta 01.10.2020.
|
|||
<string name="wallet_create_payid_empty">Inserire prima il PayString desiderato</string>
|
||||
|
||||
<string name="initial_message_scan_header">Avvicina per scansionare</string>
|
||||
<string name="initial_message_tap_header">Avvicina la scheda</string>
|
||||
<string name="initial_message_tap_header">Avvicina la carta</string>
|
||||
|
||||
<string name="details_notification_erase_wallet_not_possible">Il tuo saldo su questo portafoglio non è pari a zero o hai transazioni non confermate. Non è possibile eliminare la funzione portafoglio.</string>
|
||||
<string name="details_notification_security_option_already_active">E\' l\'opzione attualmente attiva</string>
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@
|
|||
<string name="send_error_invalid_fee_value">Invalid Fee</string>
|
||||
<string name="send_error_dust_amount_format">Minimum amount is %s</string>
|
||||
<string name="send_error_dust_change">Change is too small</string>
|
||||
<string name="send_error_no_account_xlm">To create account send 1+ XLM to this address</string>
|
||||
|
||||
<string name="wallet_notification_address_copied">Address was copied to clipboard</string>
|
||||
|
||||
|
|
|
|||
|
|
@ -35,5 +35,8 @@ this wallet.
|
|||
|
||||
<string name="send_extras_hint_memo" translatable="false">Memo</string>
|
||||
<string name="send_extras_hint_destination_tag" translatable="false">Destination tag</string>
|
||||
<string name="send_error_invalid_destination_tag" translatable="false">Invalid destination tag. It won\'t be added to the transaction</string>
|
||||
<string name="send_error_invalid_memo_id" translatable="false">Invalid Memo ID. It won\'t be added to the transaction</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ buildscript {
|
|||
classpath "com.android.tools.build:gradle:${versions.build_gradle}"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin"
|
||||
classpath "com.github.dcendents:android-maven-gradle-plugin:2.1"
|
||||
classpath 'com.google.gms:google-services:4.3.3'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.2.0'
|
||||
classpath 'com.google.gms:google-services:4.3.5'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1'
|
||||
// classpath 'com.google.firebase:perf-plugin:1.3.1'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
ext.versions = [
|
||||
kotlin : '1.4.10',
|
||||
build_gradle: '4.1.1',
|
||||
kotlin : '1.4.30',
|
||||
build_gradle: '4.1.2',
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue