Updated on 2026-08-14

This commit is contained in:
Tangem 2022-12-07 16:56:59 +03:00
parent 141c7d3936
commit 721010b489
39 changed files with 181 additions and 430 deletions

View file

@ -76,13 +76,13 @@ class DialogManager : StoreSubscriber<GlobalState> {
CreateWalletInterruptDialog.create(state.dialog, context)
is WalletConnectDialog.UnsupportedCard ->
SimpleAlertDialog.create(
titleRes = R.string.wallet_connect,
titleRes = R.string.wallet_connect_title,
messageRes = R.string.wallet_connect_scanner_error_no_ethereum_wallet,
context = context,
)
is WalletConnectDialog.AddNetwork ->
SimpleAlertDialog.create(
titleRes = R.string.wallet_connect,
titleRes = R.string.wallet_connect_title,
message = context.getString(
R.string.wallet_connect_network_not_found_format,
state.dialog.network,
@ -91,14 +91,14 @@ class DialogManager : StoreSubscriber<GlobalState> {
)
is WalletConnectDialog.OpeningSessionRejected -> {
SimpleAlertDialog.create(
titleRes = R.string.wallet_connect,
titleRes = R.string.wallet_connect_title,
messageRes = R.string.wallet_connect_same_wcuri,
context = context,
)
}
is WalletConnectDialog.SessionTimeout -> {
SimpleAlertDialog.create(
titleRes = R.string.wallet_connect,
titleRes = R.string.wallet_connect_title,
messageRes = R.string.wallet_connect_error_timeout,
context = context,
)
@ -123,7 +123,7 @@ class DialogManager : StoreSubscriber<GlobalState> {
)
is WalletConnectDialog.UnsupportedNetwork ->
SimpleAlertDialog.create(
titleRes = R.string.wallet_connect,
titleRes = R.string.wallet_connect_title,
messageRes = R.string.wallet_connect_scanner_error_unsupported_network,
context = context,
)

View file

@ -92,7 +92,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
return runTaskAsyncReturnOnMain(
ResetToFactorySettingsTask(),
card.cardId,
initialMessage = Message(context.getString(R.string.details_row_title_reset_factory_settings)),
initialMessage = Message(context.getString(R.string.card_settings_reset_card_to_factory)),
)
}

View file

@ -4,6 +4,8 @@ import com.tangem.common.CompletionResult
import com.tangem.common.card.EllipticCurve
import com.tangem.common.core.CardSession
import com.tangem.common.core.CardSessionRunnable
import com.tangem.domain.common.TwinCardNumber
import com.tangem.domain.common.TwinsHelper
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.operations.wallet.CreateWalletTask
import com.tangem.operations.wallet.PurgeWalletCommand
@ -14,8 +16,14 @@ class CreateFirstTwinWalletTask : CardSessionRunnable<CreateWalletResponse> {
session: CardSession,
callback: (result: CompletionResult<CreateWalletResponse>) -> Unit,
) {
val publicKey = session.environment.card?.getSingleWallet()?.publicKey
val card = session.environment.card
val publicKey = card?.getSingleWallet()?.publicKey
if (publicKey != null) {
if (TwinsHelper.getTwinCardNumber(card.cardId) == TwinCardNumber.Second) {
callback(CompletionResult.Failure(WrongTwinCard(TwinCardNumber.First)))
return
}
PurgeWalletCommand(publicKey).run(session) { response ->
when (response) {
is CompletionResult.Success -> {

View file

@ -6,28 +6,27 @@ import com.tangem.common.KeyPair
import com.tangem.common.card.EllipticCurve
import com.tangem.common.core.CardSession
import com.tangem.common.core.CardSessionRunnable
import com.tangem.common.core.TangemError
import com.tangem.common.extensions.hexToBytes
import com.tangem.domain.common.TwinCardNumber
import com.tangem.domain.common.TwinsHelper
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.operations.wallet.CreateWalletTask
import com.tangem.operations.wallet.PurgeWalletCommand
import com.tangem.tap.domain.extensions.getSingleWallet
import com.tangem.wallet.R
class CreateSecondTwinWalletTask(
private val firstPublicKey: String,
private val firstCardId: String,
private val issuerKeys: KeyPair,
private val preparingMessage: Message,
private val creatingWalletMessage: Message
private val creatingWalletMessage: Message,
) : CardSessionRunnable<CreateWalletResponse> {
override fun run(session: CardSession, callback: (result: CompletionResult<CreateWalletResponse>) -> Unit) {
val card = session.environment.card
val publicKey = card?.getSingleWallet()?.publicKey
if (publicKey != null) {
if (!card.cardId.startsWith(TwinsHelper.getPairCardSeries(firstCardId) ?: "")) {
callback(CompletionResult.Failure(WrongTwinCard()))
if (TwinsHelper.getTwinCardNumber(card.cardId) == TwinCardNumber.First) {
callback(CompletionResult.Failure(WrongTwinCard(TwinCardNumber.Second)))
return
}
@ -53,13 +52,10 @@ class CreateSecondTwinWalletTask(
is CompletionResult.Success -> {
session.environment.card = session.environment.card?.updateWallet(result.data.wallet)
WriteProtectedIssuerDataTask(
firstPublicKey.hexToBytes(), issuerKeys
).run(session) { writeResult ->
WriteProtectedIssuerDataTask(firstPublicKey.hexToBytes(), issuerKeys).run(session) { writeResult ->
when (writeResult) {
is CompletionResult.Success -> callback(result)
is CompletionResult.Failure ->
callback(CompletionResult.Failure(writeResult.error))
is CompletionResult.Failure -> callback(CompletionResult.Failure(writeResult.error))
}
}
}
@ -67,10 +63,4 @@ class CreateSecondTwinWalletTask(
}
}
}
private class WrongTwinCard : TangemError {
override val code: Int = 50005
override var customMessage: String = code.toString()
override val messageResId = R.string.twins_wrong_card_error
}
}

View file

@ -43,7 +43,6 @@ class TwinCardsManager(
): CompletionResult<CreateWalletResponse> {
val task = CreateSecondTwinWalletTask(
firstPublicKey = currentCardPublicKey!!,
firstCardId = currentCardId,
issuerKeys = issuerKeyPair,
preparingMessage = preparingMessage,
creatingWalletMessage = creatingWalletMessage,

View file

@ -0,0 +1,15 @@
package com.tangem.tap.domain.twins
import com.tangem.common.core.TangemError
import com.tangem.domain.common.TwinCardNumber
import com.tangem.tap.tangemSdkManager
import com.tangem.wallet.R
data class WrongTwinCard(private val twinCardNumber: TwinCardNumber) : TangemError {
override val code: Int = 50005
override var customMessage: String = tangemSdkManager.getString(
R.string.twin_error_same_card,
twinCardNumber.number,
)
override val messageResId: Int? = null
}

View file

@ -20,7 +20,7 @@ class ApproveWcSessionDialog {
session.peerMeta.url,
)
return AlertDialog.Builder(context).apply {
setTitle(context.getString(R.string.wallet_connect))
setTitle(context.getString(R.string.wallet_connect_title))
setMessage(message)
setPositiveButton(context.getText(R.string.common_start)) { _, _ ->
store.dispatch(GlobalAction.HideDialog)

View file

@ -26,14 +26,14 @@ class BnbTransactionDialog {
it.symbol,
it.price,
it.quantity,
it.amount
it.amount,
)
}.joinToString ( "\n\n" )
}.joinToString(separator = "\n\n")
is BinanceMessageData.Transfer -> context.getString(
R.string.wallet_connect_bnb_transaction_message,
data.address,
data.outputAddress,
data.amount
data.amount,
)
}
@ -44,14 +44,16 @@ class BnbTransactionDialog {
val positiveButtonTitle = context.getText(R.string.common_sign)
return AlertDialog.Builder(context).apply {
setTitle(context.getString(R.string.wallet_connect))
setTitle(context.getString(R.string.wallet_connect_title))
setMessage(fullMessage)
setPositiveButton(positiveButtonTitle) { _, _ ->
store.dispatch(WalletConnectAction.BinanceTransaction.Sign(
store.dispatch(
WalletConnectAction.BinanceTransaction.Sign(
id = sessionId,
data = data.data,
sessionData = session
))
sessionData = session,
),
)
}
setNegativeButton(context.getText(R.string.common_reject)) { _, _ ->
store.dispatch(WalletConnectAction.RejectRequest(session, sessionId))

View file

@ -13,7 +13,7 @@ class ClipboardOrScanQrDialog {
companion object {
fun create(wcUri: String, context: Context): AlertDialog {
return AlertDialog.Builder(context).apply {
setTitle(context.getString(R.string.wallet_connect))
setTitle(context.getString(R.string.wallet_connect_title))
setMessage(context.getText(R.string.wallet_connect_clipboard_alert))
setPositiveButton(context.getText(R.string.wallet_connect_paste_from_clipboard)) { _, _ ->
store.dispatch(WalletConnectAction.OpenSession(wcUri))

View file

@ -10,19 +10,10 @@ import com.trustwallet.walletconnect.models.session.WCSession
class PersonalSignDialog {
companion object {
fun create(
data: PersonalSignDialogData,
context: Context,
): AlertDialog {
val message =
context.getString(R.string.wallet_connect_alert_sign_message) +
context.getString(
R.string.wallet_connect_personal_sign_message,
data.dAppName,
data.message,
)
fun create(data: PersonalSignDialogData, context: Context): AlertDialog {
val message = context.getString(R.string.wallet_connect_alert_sign_message, data.message)
return AlertDialog.Builder(context).apply {
setTitle(context.getString(R.string.wallet_connect))
setTitle(context.getString(R.string.wallet_connect_title))
setMessage(message)
setPositiveButton(context.getText(R.string.common_sign)) { _, _ ->
store.dispatch(WalletConnectAction.SignMessage(data.session))

View file

@ -22,7 +22,7 @@ class TransactionDialog {
data.amount,
data.gasAmount,
data.totalAmount,
data.balance
data.balance,
)
val positiveButtonTitle = when (data.type) {
@ -30,7 +30,7 @@ class TransactionDialog {
WcTransactionType.EthSendTransaction -> context.getText(R.string.common_sign_and_send)
}
return AlertDialog.Builder(context).apply {
setTitle(context.getString(R.string.wallet_connect))
setTitle(context.getString(R.string.wallet_connect_title))
setMessage(message)
setPositiveButton(positiveButtonTitle) { _, _ ->
if (data.isEnoughFundsToSend) {

View file

@ -51,7 +51,7 @@ fun HomeButtons(
},
content = {
Text(
text = stringResource(id = R.string.home_button_scan),
text = stringResource(id = R.string.welcome_unlock_card),
fontWeight = FontWeight.Medium,
fontSize = 16.sp,
textAlign = TextAlign.Center,

View file

@ -178,7 +178,7 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
}
private fun setupDoneState(state: OnboardingNoteState) = with(mainBinding.onboardingActionContainer) {
btnMainAction.setText(R.string.onboarding_done_button_continue)
btnMainAction.setText(R.string.common_continue)
btnMainAction.setOnClickListener {
showConfetti(false)
store.dispatch(OnboardingNoteAction.Done)

View file

@ -91,20 +91,20 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment<OnboardingOtherCards
}
private fun setupDoneState() = with(mainBinding.onboardingActionContainer) {
btnMainAction.setText(R.string.onboarding_done_button_continue)
btnMainAction.setText(R.string.common_continue)
btnMainAction.setOnClickListener {
showConfetti(false)
store.dispatch(OnboardingOtherCardsAction.Done)
}
btnAlternativeAction.isVisible = false
btnAlternativeAction.setText("")
btnAlternativeAction.text = ""
btnAlternativeAction.setOnClickListener { }
tvHeader.setText(R.string.onboarding_done_header)
tvBody.setText(R.string.onboarding_done_body)
mainBinding.onboardingTopContainer.imvCardBackground?.setBackgroundDrawable(
mainBinding.onboardingTopContainer.imvCardBackground.setBackgroundDrawable(
requireContext().getDrawableCompat(R.drawable.shape_rectangle_rounded_8),
)
updateConstraints(R.layout.lp_onboarding_done)

View file

@ -352,7 +352,7 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
}
private fun setupDoneState(state: TwinCardsState) = with(mainBinding.onboardingActionContainer) {
btnMainAction.setText(R.string.onboarding_done_button_continue)
btnMainAction.setText(R.string.common_continue)
btnMainAction.setOnClickListener {
store.dispatch(TwinCardsAction.Confetti.Hide)
store.dispatch(TwinCardsAction.Done)

View file

@ -331,7 +331,7 @@ class OnboardingWalletFragment : BaseFragment(R.layout.fragment_onboarding_walle
tvBody.text = getString(R.string.onboarding_twins_interrupt_warning)
layoutButtonsCommon.btnWalletMainAction.text = getText(R.string.onboarding_saltpay_button_backup_origin)
} else {
tvHeader.text = getText(R.string.onboarding_title_prepare_origin)
tvHeader.text = getText(R.string.common_origin_card)
tvBody.text = getString(
R.string.onboarding_subtitle_scan_primary_card_format,
state.primaryCardId?.let { cardIdFormatter.getFormattedCardId(it) },

View file

@ -8,21 +8,21 @@ import com.tangem.tap.store
import com.tangem.wallet.R
class AddMoreBackupCardsDialog {
companion object {
fun create(context: Context): AlertDialog {
return AlertDialog.Builder(context).apply {
setTitle(R.string.alert_title)
setMessage(R.string.onboarding_alert_message_not_max_backup_cards_added)
setPositiveButton(R.string.common_continue) { _, _ ->
store.dispatch(BackupAction.ShowAccessCodeInfoScreen)
}
setNegativeButton(R.string.onboarding_button_add_more_cards) { _, _ ->
companion object {
fun create(context: Context): AlertDialog {
return AlertDialog.Builder(context).apply {
setTitle(R.string.alert_title)
setMessage(R.string.onboarding_alert_message_not_max_backup_cards_added)
setPositiveButton(R.string.common_continue) { _, _ ->
store.dispatch(BackupAction.ShowAccessCodeInfoScreen)
}
setNegativeButton(R.string.common_cancel) { _, _ ->
}
setOnDismissListener {
store.dispatch(GlobalAction.HideDialog)
}
}.create()
}
}
setOnDismissListener {
store.dispatch(GlobalAction.HideDialog)
}
}.create()
}
}
}

View file

@ -230,12 +230,12 @@ class SendStateSubscriber(fragment: BaseStoreFragment) :
val balanceText = when (state.mainCurrency.type) {
MainCurrencyType.FIAT -> fg.getString(
R.string.send_balance_subtitle_format,
state.viewBalanceValue, state.mainCurrency.currencySymbol,
R.string.common_balance,
"${state.viewBalanceValue} ${state.mainCurrency.currencySymbol}",
).remove(":")
MainCurrencyType.CRYPTO -> fg.getString(
R.string.send_balance_subtitle_format,
state.mainCurrency.currencySymbol, state.viewBalanceValue,
R.string.common_balance,
"${state.mainCurrency.currencySymbol} ${state.viewBalanceValue}",
)
}
@ -304,7 +304,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) :
val willSent = getString(
R.string.send_total_subtitle_format,
receipt.willSentCrypto, receipt.symbols.crypto,
"${receipt.willSentCrypto} ${receipt.symbols.crypto}",
)
llTotalContainer.tvWillBeSentValue.update(willSent)
}
@ -316,15 +316,13 @@ class SendStateSubscriber(fragment: BaseStoreFragment) :
tvReceiptAmountValue.update("${receipt.amountCrypto} ${receipt.symbols.crypto}")
tvReceiptFeeValue.update("${receipt.feeCrypto} ${receipt.symbols.crypto}")
llTotalContainer.tvTotalValue.update("${receipt.totalCrypto} ${receipt.symbols.crypto}")
val willSent = SpannableStringBuilder()
.bold {
append(roughOrEmpty(receipt.willSentFiat)).append(" ")
append(receipt.symbols.fiat)
append(" (fee: ${receipt.feeFiat} ")
append(receipt.symbols.fiat).append(")")
}
llTotalContainer.tvWillBeSentValue.update(willSent.toString())
llTotalContainer.tvWillBeSentValue.update(
getString(
R.string.send_total_subtitle_fiat_format,
"${roughOrEmpty(receipt.willSentFiat)} ${receipt.symbols.fiat}",
"${receipt.feeFiat} ${receipt.symbols.fiat}",
),
)
}
ReceiptLayoutType.TOKEN_FIAT -> {
val receipt = state.tokenFiat ?: return
@ -337,8 +335,8 @@ class SendStateSubscriber(fragment: BaseStoreFragment) :
val willSent = getString(
R.string.send_total_subtitle_asset_format,
receipt.symbols.token ?: "", receipt.willSentToken,
receipt.symbols.crypto, receipt.willSentFeeCoin,
"${receipt.symbols.token ?: ""} ${receipt.willSentToken}",
"${receipt.symbols.crypto} ${receipt.willSentFeeCoin}",
)
llTotalContainer.tvWillBeSentValue.update(willSent)
}

View file

@ -13,9 +13,9 @@ import com.tangem.wallet.R
@Composable
fun SelectTokenNetworkDialog(dialog: DomainDialog.SelectTokenDialog, onDismissRequest: () -> Unit) {
SimpleDialog(
title = stringResource(id = R.string.custom_token_type_network),
title = stringResource(id = R.string.custom_token_network_input_title),
items = dialog.items,
onSelect = dialog.onSelect,
onDismissRequest = onDismissRequest
onDismissRequest = onDismissRequest,
) { network -> TitleSubtitle(dialog.networkIdConverter(network.networkId), network.contractAddress ?: "") }
}

View file

@ -118,7 +118,7 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
override fun newState(state: TokensState) {
if (activity == null || view == null) return
val toolbarTitle =
if (state.allowToAdd) R.string.add_tokens_title else R.string.search_tokens_title
if (state.allowToAdd) R.string.main_manage_tokens else R.string.search_tokens_title
tokensState.value = state
binding.toolbar.title = getString(toolbarTitle)
}
@ -143,7 +143,7 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
val menuItem = menu.findItem(R.id.menu_search)
val searchView: SearchView = menuItem.actionView as SearchView
searchView.queryHint = searchView.getString(R.string.add_token_search_hint)
searchView.queryHint = searchView.getString(R.string.common_search)
searchView.maxWidth = android.R.attr.width
searchView.inputtedTextAsFlow()
.debounce(800)

View file

@ -91,8 +91,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
(activity as? AppCompatActivity)?.setSupportActionBar(binding.toolbar)
binding.toolbar.setNavigationOnClickListener {
Analytics.send(MainScreen.ButtonScanCard())
store.dispatch(WalletAction.Scan)
store.dispatch(NavigationAction.NavigateTo(AppScreen.Send))
}
setupWarningsRecyclerView()
walletView.changeWalletView(this, binding)