Updated on 2026-08-14
This commit is contained in:
parent
8ce2b8d52b
commit
f34aeba4ed
18 changed files with 222 additions and 199 deletions
|
|
@ -7,6 +7,8 @@ import com.tangem.tap.common.redux.global.GlobalState
|
|||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectDialog
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.*
|
||||
import com.tangem.tap.features.onboarding.AddressInfoBottomSheetDialog
|
||||
import com.tangem.tap.features.twins.redux.TwinCardsAction
|
||||
import com.tangem.tap.features.twins.ui.dialog.CreateWalletInterruptDialog
|
||||
import com.tangem.tap.features.wallet.ui.dialogs.ScanFailsDialog
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -43,24 +45,25 @@ class DialogManager : StoreSubscriber<GlobalState> {
|
|||
dialog = when (state.dialog) {
|
||||
is AppDialog.ScanFailsDialog -> ScanFailsDialog.create(context)
|
||||
is AppDialog.AddressInfoDialog -> AddressInfoBottomSheetDialog(state.dialog, context)
|
||||
is TwinCardsAction.Wallet.InterruptDialog -> CreateWalletInterruptDialog.create(state.dialog, context)
|
||||
is WalletConnectDialog.UnsupportedCard ->
|
||||
SimpleAlertDialog.create(
|
||||
titleRes = R.string.wallet_connect,
|
||||
messageRes = R.string.wallet_connect_scanner_error_no_ethereum_wallet,
|
||||
context = context
|
||||
titleRes = R.string.wallet_connect,
|
||||
messageRes = R.string.wallet_connect_scanner_error_no_ethereum_wallet,
|
||||
context = context
|
||||
)
|
||||
is WalletConnectDialog.OpeningSessionRejected -> {
|
||||
SimpleAlertDialog.create(
|
||||
titleRes = R.string.wallet_connect,
|
||||
messageRes = R.string.wallet_connect_same_wcuri,
|
||||
context = context
|
||||
titleRes = R.string.wallet_connect,
|
||||
messageRes = R.string.wallet_connect_same_wcuri,
|
||||
context = context
|
||||
)
|
||||
}
|
||||
is WalletConnectDialog.SessionTimeout -> {
|
||||
SimpleAlertDialog.create(
|
||||
titleRes = R.string.wallet_connect,
|
||||
messageRes = R.string.wallet_connect_error_timeout,
|
||||
context = context
|
||||
titleRes = R.string.wallet_connect,
|
||||
messageRes = R.string.wallet_connect_error_timeout,
|
||||
context = context
|
||||
)
|
||||
}
|
||||
is WalletConnectDialog.ApproveWcSession ->
|
||||
|
|
|
|||
|
|
@ -16,9 +16,7 @@ import com.tangem.tap.domain.configurable.config.ConfigManager
|
|||
import com.tangem.tap.domain.extensions.*
|
||||
import com.tangem.tap.domain.tasks.product.ScanResponse
|
||||
import com.tangem.tap.domain.tokens.CardCurrencies
|
||||
import com.tangem.tap.domain.twins.getTwinCardNumber
|
||||
import com.tangem.tap.features.tokens.redux.TokensAction
|
||||
import com.tangem.tap.features.twins.redux.TwinCardsAction
|
||||
import com.tangem.tap.features.wallet.redux.Currency
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.network.NetworkConnectivity
|
||||
|
|
@ -82,20 +80,13 @@ class TapWalletManager {
|
|||
FirebaseAnalyticsHandler.triggerEvent(AnalyticsEvent.CARD_IS_SCANNED, data.card, data.walletData?.blockchain)
|
||||
}
|
||||
store.state.globalState.feedbackManager?.infoHolder?.setCardInfo(data.card)
|
||||
val configManager = store.state.globalState.configManager
|
||||
updateConfigManager(configManager, data)
|
||||
updateConfigManager(data)
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
store.dispatch(WalletAction.ResetState)
|
||||
store.dispatch(GlobalAction.SaveScanNoteResponse(data))
|
||||
store.dispatch(WalletAction.SetIfTestnetCard(data.card.isTestCard))
|
||||
store.dispatch(WalletAction.MultiWallet.SetIsMultiwalletAllowed(data.card.isMultiwalletAllowed))
|
||||
if (data.isTangemTwins()) {
|
||||
data.card.getTwinCardNumber()?.let {
|
||||
val isCreatingTwinsAllowed = configManager?.config?.isCreatingTwinCardsAllowed ?: false
|
||||
store.dispatch(TwinCardsAction.SetTwinCard(it, null, isCreatingTwinsAllowed))
|
||||
}
|
||||
}
|
||||
|
||||
val blockchain = data.getBlockchain()
|
||||
if (blockchain == Blockchain.Ethereum ||
|
||||
|
|
@ -106,7 +97,8 @@ class TapWalletManager {
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateConfigManager(configManager: ConfigManager?, data: ScanResponse) {
|
||||
private fun updateConfigManager(data: ScanResponse) {
|
||||
val configManager = store.state.globalState.configManager
|
||||
val blockchain = data.getBlockchain()
|
||||
if (data.card.isStart2Coin) {
|
||||
configManager?.turnOff(ConfigManager.isSendingToPayIdEnabled)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.domain.twins
|
||||
|
||||
import android.content.Context
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Types
|
||||
import com.tangem.Message
|
||||
|
|
@ -12,24 +11,21 @@ import com.tangem.common.core.TangemSdkError
|
|||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler
|
||||
import com.tangem.tap.common.extensions.readAssetAsString
|
||||
import com.tangem.tap.domain.tasks.product.ScanResponse
|
||||
import com.tangem.tap.network.createMoshi
|
||||
import com.tangem.tap.tangemSdkManager
|
||||
|
||||
class TwinCardsManager(private val scanResponse: ScanResponse, context: Context) {
|
||||
class TwinCardsManager(private val scanResponse: ScanResponse, assetReader: AssetReader) {
|
||||
|
||||
private val currentCardId: String = scanResponse.card.cardId
|
||||
|
||||
// private val secondCardId: String? = TwinsHelper.getTwinsCardId(currentCardId)
|
||||
// private val secondCardId: Strings? = TwinsHelper.getTwinsCardId(currentCardId)
|
||||
private val secondCardId: String? = null
|
||||
|
||||
private var currentCardPublicKey: String? = null
|
||||
private var secondCardPublicKey: String? = null
|
||||
|
||||
private val issuerKeyPair: KeyPair = getIssuerKeys(
|
||||
context, scanResponse.card.issuer.publicKey.toHexString()
|
||||
)
|
||||
private val issuerKeyPair: KeyPair = getIssuerKeys(assetReader, scanResponse.card.issuer.publicKey.toHexString())
|
||||
|
||||
suspend fun createFirstWallet(message: Message): SimpleResult {
|
||||
val response = tangemSdkManager.runTaskAsync(
|
||||
|
|
@ -108,8 +104,8 @@ class TwinCardsManager(private val scanResponse: ScanResponse, context: Context)
|
|||
}
|
||||
|
||||
companion object {
|
||||
private fun getIssuerKeys(context: Context, publicKey: String): KeyPair {
|
||||
val issuer = getIssuers(context).first { it.publicKey == publicKey }
|
||||
private fun getIssuerKeys(reader: AssetReader, publicKey: String): KeyPair {
|
||||
val issuer = getIssuers(reader).first { it.publicKey == publicKey }
|
||||
return KeyPair(
|
||||
publicKey = issuer.publicKey.hexToBytes(),
|
||||
privateKey = issuer.privateKey.hexToBytes()
|
||||
|
|
@ -122,13 +118,17 @@ class TwinCardsManager(private val scanResponse: ScanResponse, context: Context)
|
|||
)
|
||||
}
|
||||
|
||||
private fun getIssuers(context: Context): List<Issuer> {
|
||||
val file = context.readAssetAsString("tangem-app-config/issuers")
|
||||
private fun getIssuers(reader: AssetReader): List<Issuer> {
|
||||
val file = reader.readAssetAsString("tangem-app-config/issuers")
|
||||
return getAdapter().fromJson(file)!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface AssetReader {
|
||||
fun readAssetAsString(name: String): String
|
||||
}
|
||||
|
||||
private class Issuer(
|
||||
val id: String,
|
||||
val privateKey: String,
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class DetailsFragment : Fragment(R.layout.fragment_details), StoreSubscriber<Det
|
|||
tv_erase_wallet.show()
|
||||
tv_erase_wallet.text = getText(R.string.details_row_title_twins_recreate)
|
||||
tv_erase_wallet.setOnClickListener {
|
||||
store.dispatch(TwinCardsAction.CreateWallet.Create(
|
||||
store.dispatch(TwinCardsAction.Wallet.Create(
|
||||
state.twinCardsState.cardNumber!!,
|
||||
CreateTwinWalletMode.RecreateWallet
|
||||
))
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@ import com.tangem.tap.common.redux.navigation.AppScreen
|
|||
import com.tangem.tap.common.redux.navigation.FragmentShareTransition
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.domain.twins.getTwinCardNumber
|
||||
import com.tangem.tap.features.onboarding.OnboardingHelper
|
||||
import com.tangem.tap.features.send.redux.states.ButtonState
|
||||
import com.tangem.tap.features.twins.redux.TwinCardsAction
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -56,6 +58,14 @@ private fun handleReadCard() {
|
|||
} else {
|
||||
changeButtonState(ButtonState.PROGRESS)
|
||||
store.dispatch(GlobalAction.ScanCard({ scanResponse ->
|
||||
if (scanResponse.isTangemTwins()) {
|
||||
scanResponse.card.getTwinCardNumber()?.let {
|
||||
val configManager = store.state.globalState.configManager
|
||||
val isCreatingTwinsAllowed = configManager?.config?.isCreatingTwinCardsAllowed ?: false
|
||||
store.dispatch(TwinCardsAction.SetTwinCard(it, null, isCreatingTwinsAllowed))
|
||||
}
|
||||
}
|
||||
|
||||
if (OnboardingHelper.isOnboardingCase(scanResponse)) {
|
||||
val navigateTo = OnboardingHelper.whereToNavigate(scanResponse)
|
||||
store.dispatch(GlobalAction.Onboarding.Start(scanResponse))
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@ import com.tangem.tap.common.postUi
|
|||
import com.tangem.tap.common.toggleWidget.RefreshBalanceWidget
|
||||
import com.tangem.tap.common.transitions.InternalNoteLayoutTransition
|
||||
import com.tangem.tap.features.onboarding.products.BaseOnboardingFragment
|
||||
import com.tangem.tap.features.onboarding.products.note.redux.*
|
||||
import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteAction
|
||||
import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteResources
|
||||
import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteState
|
||||
import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteStep
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.fragment_onboarding_main.*
|
||||
|
|
@ -43,14 +46,14 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
|
|||
|
||||
toolbar.setTitle(R.string.onboarding_title)
|
||||
btnRefreshBalanceWidget = RefreshBalanceWidget(onboarding_main_container)
|
||||
val resources = AndroidResources(
|
||||
OnboardingStringResources(
|
||||
|
||||
val resources = OnboardingNoteResources(
|
||||
OnboardingNoteResources.Strings(
|
||||
R.string.copy_toast_msg
|
||||
)
|
||||
)
|
||||
|
||||
store.dispatch(OnboardingNoteAction.LoadCardArtwork)
|
||||
store.dispatch(OnboardingNoteAction.SetResources(resources))
|
||||
store.dispatch(OnboardingNoteAction.LoadCardArtwork)
|
||||
store.dispatch(OnboardingNoteAction.DetermineStepOfScreen)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import org.rekotlin.Action
|
|||
*/
|
||||
sealed class OnboardingNoteAction : Action {
|
||||
// from user, ui
|
||||
data class SetResources(val resources: AndroidResources) : OnboardingNoteAction()
|
||||
data class SetResources(val resources: OnboardingNoteResources) : OnboardingNoteAction()
|
||||
object LoadCardArtwork : OnboardingNoteAction()
|
||||
object CreateWallet : OnboardingNoteAction()
|
||||
object TopUp : OnboardingNoteAction()
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import org.rekotlin.StateType
|
|||
*/
|
||||
data class OnboardingNoteState(
|
||||
val walletManager: WalletManager? = null,
|
||||
val resources: AndroidResources = AndroidResources(),
|
||||
val resources: OnboardingNoteResources = OnboardingNoteResources(),
|
||||
// UI
|
||||
val cardArtwork: Artwork? = null,
|
||||
val walletBalance: OnboardingWalletBalance = OnboardingWalletBalance.loading(),
|
||||
|
|
@ -27,10 +27,10 @@ enum class OnboardingNoteStep {
|
|||
None, CreateWallet, TopUpWallet, Done
|
||||
}
|
||||
|
||||
data class AndroidResources(
|
||||
val strings: OnboardingStringResources = OnboardingStringResources()
|
||||
)
|
||||
|
||||
data class OnboardingStringResources(
|
||||
val addressWasCopied: Int = -1
|
||||
)
|
||||
data class OnboardingNoteResources(
|
||||
val strings: Strings = Strings()
|
||||
) {
|
||||
data class Strings(
|
||||
val addressWasCopied: Int = -1
|
||||
)
|
||||
}
|
||||
|
|
@ -1,62 +1,62 @@
|
|||
package com.tangem.tap.features.twins.redux
|
||||
|
||||
import android.content.Context
|
||||
import com.tangem.Message
|
||||
import com.tangem.tap.common.redux.NotificationAction
|
||||
import com.tangem.tap.common.redux.StateDialog
|
||||
import com.tangem.tap.domain.tasks.product.ScanResponse
|
||||
import com.tangem.tap.domain.twins.AssetReader
|
||||
import com.tangem.tap.domain.twins.TwinCardNumber
|
||||
import com.tangem.wallet.R
|
||||
import com.tangem.tap.domain.twins.TwinCardsManager
|
||||
import org.rekotlin.Action
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
sealed class TwinCardsAction : Action {
|
||||
object ShowOnboarding : TwinCardsAction()
|
||||
object SetOnboardingShown : TwinCardsAction()
|
||||
|
||||
data class SetResources(val resources: TwinCardsResources) : TwinCardsAction()
|
||||
|
||||
data class SetTwinCard(
|
||||
val number: TwinCardNumber,
|
||||
val secondCardId: String?,
|
||||
val isCreatingTwinCardsAllowed: Boolean,
|
||||
) : TwinCardsAction()
|
||||
|
||||
sealed class CreateWallet : TwinCardsAction() {
|
||||
sealed class CardsManager {
|
||||
data class Set(val manager: TwinCardsManager) : TwinCardsAction()
|
||||
object Release : TwinCardsAction()
|
||||
}
|
||||
|
||||
object ShowOnboarding : TwinCardsAction()
|
||||
object SetOnboardingShown : TwinCardsAction()
|
||||
object ProceedToCreateWallet : TwinCardsAction()
|
||||
|
||||
sealed class Wallet : TwinCardsAction() {
|
||||
object HandleOnBackPressed : TwinCardsAction()
|
||||
|
||||
data class Create(
|
||||
val number: TwinCardNumber,
|
||||
val createTwinWalletMode: CreateTwinWalletMode
|
||||
) : CreateWallet()
|
||||
) : TwinCardsAction()
|
||||
|
||||
object NotEmpty : CreateWallet(), NotificationAction {
|
||||
override val messageResource = R.string.details_notification_erase_wallet_not_possible
|
||||
}
|
||||
|
||||
object ShowAlert : CreateWallet()
|
||||
object HideAlert : CreateWallet()
|
||||
object Proceed : CreateWallet()
|
||||
|
||||
object Cancel : CreateWallet() {
|
||||
object Confirm : CreateWallet()
|
||||
}
|
||||
data class InterruptDialog(val interrupt: () -> Unit) : TwinCardsAction(), StateDialog
|
||||
|
||||
data class LaunchFirstStep(
|
||||
val message: Message, val context: Context
|
||||
) : CreateWallet() {
|
||||
object Success : CreateWallet()
|
||||
object Failure : CreateWallet()
|
||||
val initialMessage: Message,
|
||||
val reader: AssetReader
|
||||
) : TwinCardsAction() {
|
||||
object Success : TwinCardsAction()
|
||||
}
|
||||
|
||||
data class LaunchSecondStep(
|
||||
val initialMessage: Message,
|
||||
val preparingMessage: Message,
|
||||
val creatingWalletMessage: Message,
|
||||
) : CreateWallet() {
|
||||
object Success : CreateWallet()
|
||||
object Failure : CreateWallet()
|
||||
) : TwinCardsAction() {
|
||||
object Success : TwinCardsAction()
|
||||
}
|
||||
|
||||
data class LaunchThirdStep(val message: Message) : CreateWallet() {
|
||||
data class Success(val scanResponse: ScanResponse) : CreateWallet()
|
||||
object Failure : CreateWallet()
|
||||
data class LaunchThirdStep(val message: Message) : TwinCardsAction() {
|
||||
data class Success(val scanResponse: ScanResponse) : TwinCardsAction()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.tangem.tap.features.twins.redux
|
|||
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.blockchain.extensions.SimpleResult
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchNotification
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
|
|
@ -32,12 +34,11 @@ private val twinsWalletMiddleware: Middleware<AppState> = { dispatch, state ->
|
|||
}
|
||||
}
|
||||
|
||||
private var twinsManager: TwinCardsManager? = null
|
||||
|
||||
private fun handle(action: Action, dispatch: DispatchFunction) {
|
||||
val action = action as? TwinCardsAction ?: return
|
||||
|
||||
val twinCardsState = store.state.twinCardsState
|
||||
|
||||
when (action) {
|
||||
is TwinCardsAction.SetTwinCard -> {
|
||||
val showOnboarding = !preferencesStorage.wasTwinsOnboardingShown()
|
||||
|
|
@ -46,7 +47,22 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
TwinCardsAction.SetOnboardingShown -> {
|
||||
preferencesStorage.saveTwinsOnboardingShown()
|
||||
}
|
||||
is TwinCardsAction.CreateWallet.Create -> {
|
||||
is TwinCardsAction.ProceedToCreateWallet -> {
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.CreateTwinWallet))
|
||||
}
|
||||
is TwinCardsAction.Wallet.HandleOnBackPressed -> {
|
||||
if (twinCardsState.createWalletState?.showAlert == true) {
|
||||
val stateDialog = TwinCardsAction.Wallet.InterruptDialog {
|
||||
store.dispatch(TwinCardsAction.CardsManager.Release)
|
||||
store.dispatch(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
}
|
||||
store.dispatchDialogShow(stateDialog)
|
||||
} else {
|
||||
store.dispatch(TwinCardsAction.CardsManager.Release)
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
}
|
||||
}
|
||||
is TwinCardsAction.Wallet.Create -> {
|
||||
val wallet = store.state.walletState.walletManagers.map { it.wallet }.firstOrNull()
|
||||
if (wallet == null) {
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.CreateTwinWalletWarning))
|
||||
|
|
@ -54,90 +70,70 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
|
|||
}
|
||||
val notEmpty = wallet.recentTransactions.isNotEmpty() || wallet.amounts.toSendableAmounts().isNotEmpty()
|
||||
if (notEmpty) {
|
||||
store.dispatch(TwinCardsAction.CreateWallet.NotEmpty)
|
||||
store.dispatchNotification(twinCardsState.resources.strings.walletIsNotEmpty)
|
||||
} else {
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.CreateTwinWalletWarning))
|
||||
}
|
||||
}
|
||||
is TwinCardsAction.CreateWallet.Proceed -> {
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.CreateTwinWallet))
|
||||
}
|
||||
is TwinCardsAction.CreateWallet.Cancel -> {
|
||||
val step = twinCardsState.createWalletState?.step
|
||||
if (step != null && step != CreateTwinWalletStep.FirstStep) {
|
||||
store.dispatch(TwinCardsAction.CreateWallet.ShowAlert)
|
||||
} else {
|
||||
twinsManager = null
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
}
|
||||
}
|
||||
is TwinCardsAction.CreateWallet.Cancel.Confirm -> {
|
||||
twinsManager = null
|
||||
store.dispatch(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
}
|
||||
is TwinCardsAction.CreateWallet.LaunchFirstStep -> {
|
||||
store.state.globalState.scanResponse?.let {
|
||||
twinsManager = TwinCardsManager(it, action.context)
|
||||
}
|
||||
is TwinCardsAction.Wallet.LaunchFirstStep -> {
|
||||
val scanResponse = store.state.globalState.scanResponse ?: return
|
||||
|
||||
val manager = TwinCardsManager(scanResponse, action.reader)
|
||||
store.dispatch(TwinCardsAction.CardsManager.Set(manager))
|
||||
|
||||
scope.launch {
|
||||
val result = twinsManager?.createFirstWallet(action.message)
|
||||
val result = manager.createFirstWallet(action.initialMessage)
|
||||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
SimpleResult.Success ->
|
||||
store.dispatch(TwinCardsAction.CreateWallet.LaunchFirstStep.Success)
|
||||
is SimpleResult.Failure ->
|
||||
store.dispatch(TwinCardsAction.CreateWallet.LaunchFirstStep.Failure)
|
||||
SimpleResult.Success -> {
|
||||
store.dispatch(TwinCardsAction.Wallet.LaunchFirstStep.Success)
|
||||
}
|
||||
is SimpleResult.Failure -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TwinCardsAction.CreateWallet.LaunchFirstStep.Success -> {
|
||||
is TwinCardsAction.Wallet.LaunchSecondStep -> {
|
||||
val manager = twinCardsState.twinCardsManager ?: return
|
||||
|
||||
}
|
||||
TwinCardsAction.CreateWallet.LaunchFirstStep.Failure -> {
|
||||
|
||||
}
|
||||
is TwinCardsAction.CreateWallet.LaunchSecondStep ->
|
||||
scope.launch {
|
||||
val result = twinsManager?.createSecondWallet(action.initialMessage,
|
||||
val result = manager.createSecondWallet(action.initialMessage,
|
||||
action.preparingMessage, action.creatingWalletMessage)
|
||||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
SimpleResult.Success ->
|
||||
store.dispatch(TwinCardsAction.CreateWallet.LaunchSecondStep.Success)
|
||||
is SimpleResult.Failure ->
|
||||
store.dispatch(TwinCardsAction.CreateWallet.LaunchSecondStep.Failure)
|
||||
SimpleResult.Success -> {
|
||||
store.dispatch(TwinCardsAction.Wallet.LaunchSecondStep.Success)
|
||||
}
|
||||
is SimpleResult.Failure -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TwinCardsAction.CreateWallet.LaunchSecondStep.Success -> {
|
||||
|
||||
}
|
||||
TwinCardsAction.CreateWallet.LaunchSecondStep.Failure -> {
|
||||
is TwinCardsAction.Wallet.LaunchThirdStep -> {
|
||||
val manager = twinCardsState.twinCardsManager ?: return
|
||||
|
||||
}
|
||||
is TwinCardsAction.CreateWallet.LaunchThirdStep -> {
|
||||
scope.launch {
|
||||
val result = twinsManager?.complete(action.message)
|
||||
val result = manager.complete(action.message)
|
||||
withContext(Dispatchers.Main) {
|
||||
when (result) {
|
||||
is Result.Success ->
|
||||
store.dispatch(TwinCardsAction.CreateWallet.LaunchThirdStep.Success(result.data))
|
||||
is Result.Failure ->
|
||||
store.dispatch(TwinCardsAction.CreateWallet.LaunchThirdStep.Failure)
|
||||
is Result.Success -> {
|
||||
store.dispatch(TwinCardsAction.Wallet.LaunchThirdStep.Success(result.data))
|
||||
}
|
||||
is Result.Failure -> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is TwinCardsAction.CreateWallet.LaunchThirdStep.Success -> {
|
||||
is TwinCardsAction.Wallet.LaunchThirdStep.Success -> {
|
||||
scope.launch {
|
||||
store.state.globalState.tapWalletManager.onCardScanned(action.scanResponse)
|
||||
}
|
||||
store.dispatch(NavigationAction.PopBackTo(AppScreen.Home))
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Wallet))
|
||||
}
|
||||
TwinCardsAction.CreateWallet.LaunchThirdStep.Failure -> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,52 +12,49 @@ class TwinCardsReducer {
|
|||
private fun internalReduce(action: Action, state: AppState): TwinCardsState {
|
||||
if (action !is TwinCardsAction) return state.twinCardsState
|
||||
|
||||
val twinCardsState = state.twinCardsState
|
||||
val state = state.twinCardsState
|
||||
return when (action) {
|
||||
is TwinCardsAction.SetResources -> {
|
||||
state.copy(resources = action.resources)
|
||||
}
|
||||
is TwinCardsAction.SetTwinCard -> {
|
||||
twinCardsState.copy(
|
||||
state.copy(
|
||||
cardNumber = action.number,
|
||||
secondCardId = action.secondCardId,
|
||||
showTwinOnboarding = state.twinCardsState.showTwinOnboarding,
|
||||
showTwinOnboarding = state.showTwinOnboarding,
|
||||
isCreatingTwinCardsAllowed = action.isCreatingTwinCardsAllowed,
|
||||
)
|
||||
}
|
||||
is TwinCardsAction.CardsManager.Set -> {
|
||||
state.copy(twinCardsManager = action.manager)
|
||||
}
|
||||
TwinCardsAction.CardsManager.Release -> {
|
||||
state.copy(twinCardsManager = null)
|
||||
}
|
||||
is TwinCardsAction.ShowOnboarding -> {
|
||||
state.twinCardsState.copy(showTwinOnboarding = true)
|
||||
state.copy(showTwinOnboarding = true)
|
||||
}
|
||||
is TwinCardsAction.SetOnboardingShown -> {
|
||||
twinCardsState.copy(showTwinOnboarding = false)
|
||||
state.copy(showTwinOnboarding = false)
|
||||
}
|
||||
is TwinCardsAction.CreateWallet.Create -> {
|
||||
val prevState = twinCardsState.createWalletState
|
||||
twinCardsState.copy(createWalletState = CreateTwinWalletState(
|
||||
is TwinCardsAction.Wallet.Create -> {
|
||||
val prevState = state.createWalletState
|
||||
state.copy(createWalletState = CreateTwinWalletState(
|
||||
prevState?.scanResponse,
|
||||
prevState?.number ?: action.number,
|
||||
prevState?.mode ?: action.createTwinWalletMode,
|
||||
))
|
||||
}
|
||||
TwinCardsAction.CreateWallet.LaunchFirstStep.Success -> {
|
||||
twinCardsState.copy(createWalletState = twinCardsState.createWalletState?.copy(
|
||||
TwinCardsAction.Wallet.LaunchFirstStep.Success -> {
|
||||
state.copy(createWalletState = state.createWalletState?.copy(
|
||||
step = CreateTwinWalletStep.SecondStep
|
||||
))
|
||||
}
|
||||
TwinCardsAction.CreateWallet.LaunchSecondStep.Success ->
|
||||
twinCardsState.copy(createWalletState = twinCardsState.createWalletState?.copy(
|
||||
TwinCardsAction.Wallet.LaunchSecondStep.Success ->
|
||||
state.copy(createWalletState = state.createWalletState?.copy(
|
||||
step = CreateTwinWalletStep.ThirdStep
|
||||
))
|
||||
TwinCardsAction.CreateWallet.ShowAlert -> twinCardsState
|
||||
TwinCardsAction.CreateWallet.HideAlert -> twinCardsState
|
||||
is TwinCardsAction.CreateWallet.Proceed -> twinCardsState
|
||||
TwinCardsAction.CreateWallet.NotEmpty -> twinCardsState
|
||||
TwinCardsAction.CreateWallet.Cancel -> twinCardsState
|
||||
TwinCardsAction.CreateWallet.Cancel.Confirm -> twinCardsState
|
||||
is TwinCardsAction.CreateWallet.LaunchFirstStep -> twinCardsState
|
||||
TwinCardsAction.CreateWallet.LaunchFirstStep.Failure -> twinCardsState
|
||||
is TwinCardsAction.CreateWallet.LaunchSecondStep -> twinCardsState
|
||||
TwinCardsAction.CreateWallet.LaunchSecondStep.Failure -> twinCardsState
|
||||
is TwinCardsAction.CreateWallet.LaunchThirdStep -> twinCardsState
|
||||
is TwinCardsAction.CreateWallet.LaunchThirdStep.Success -> twinCardsState
|
||||
TwinCardsAction.CreateWallet.LaunchThirdStep.Failure -> twinCardsState
|
||||
else -> state
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,22 +2,22 @@ package com.tangem.tap.features.twins.redux
|
|||
|
||||
import com.tangem.tap.domain.tasks.product.ScanResponse
|
||||
import com.tangem.tap.domain.twins.TwinCardNumber
|
||||
import com.tangem.tap.domain.twins.TwinCardsManager
|
||||
import org.rekotlin.StateType
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
data class TwinCardsState(
|
||||
val twinCardsManager: TwinCardsManager? = null,
|
||||
// if cardNumber is not set -> the scanned card is not Twin
|
||||
val cardNumber: TwinCardNumber? = null,
|
||||
val secondCardId: String? = null,
|
||||
val showTwinOnboarding: Boolean = false,
|
||||
val isCreatingTwinCardsAllowed: Boolean = false,
|
||||
val createWalletState: CreateTwinWalletState? = null
|
||||
) : StateType {
|
||||
val isReadyToUse: Boolean
|
||||
get() = cardNumber != null
|
||||
}
|
||||
val createWalletState: CreateTwinWalletState? = null,
|
||||
val resources: TwinCardsResources = TwinCardsResources(),
|
||||
) : StateType
|
||||
|
||||
data class CreateTwinWalletState(
|
||||
val scanResponse: ScanResponse?,
|
||||
|
|
@ -26,9 +26,18 @@ data class CreateTwinWalletState(
|
|||
val step: CreateTwinWalletStep = CreateTwinWalletStep.FirstStep,
|
||||
) {
|
||||
val showAlert: Boolean
|
||||
get() = mode != CreateTwinWalletMode.RecreateWallet
|
||||
get() = step != CreateTwinWalletStep.FirstStep
|
||||
}
|
||||
|
||||
enum class CreateTwinWalletStep { FirstStep, SecondStep, ThirdStep }
|
||||
|
||||
enum class CreateTwinWalletMode { CreateWallet, RecreateWallet }
|
||||
|
||||
data class TwinCardsResources(
|
||||
val strings: Strings = Strings()
|
||||
) {
|
||||
//TODO: create global structure for StringRes. Set it from the MainActivity.
|
||||
data class Strings(
|
||||
val walletIsNotEmpty: Int = -1
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
package com.tangem.tap.features.twins.ui
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.core.content.ContextCompat.getColor
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.transition.TransitionInflater
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.tangem.Message
|
||||
import com.tangem.tap.common.extensions.readAssetAsString
|
||||
import com.tangem.tap.domain.twins.AssetReader
|
||||
import com.tangem.tap.domain.twins.TwinCardNumber
|
||||
import com.tangem.tap.features.twins.redux.CreateTwinWalletMode
|
||||
import com.tangem.tap.features.twins.redux.CreateTwinWalletStep
|
||||
import com.tangem.tap.features.twins.redux.TwinCardsAction
|
||||
import com.tangem.tap.features.twins.redux.TwinCardsState
|
||||
import com.tangem.tap.features.twins.redux.*
|
||||
import com.tangem.tap.features.wallet.redux.Artwork
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -24,20 +21,35 @@ import org.rekotlin.StoreSubscriber
|
|||
class CreateTwinWalletFragment : Fragment(R.layout.fragment_twin_cards_create),
|
||||
StoreSubscriber<TwinCardsState> {
|
||||
|
||||
private var dialog: Dialog? = null
|
||||
private val assetReader: AssetReader by lazy {
|
||||
object : AssetReader {
|
||||
override fun readAssetAsString(name: String): String = requireContext().readAssetAsString(name)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
store.dispatch(TwinCardsAction.CreateWallet.Cancel)
|
||||
store.dispatch(TwinCardsAction.Wallet.HandleOnBackPressed)
|
||||
}
|
||||
})
|
||||
|
||||
initResources()
|
||||
val inflater = TransitionInflater.from(requireContext())
|
||||
enterTransition = inflater.inflateTransition(R.transition.slide_right)
|
||||
exitTransition = inflater.inflateTransition(R.transition.fade)
|
||||
}
|
||||
|
||||
private fun initResources() {
|
||||
val resources = TwinCardsResources(
|
||||
TwinCardsResources.Strings(
|
||||
R.string.details_notification_erase_wallet_not_possible
|
||||
)
|
||||
)
|
||||
store.dispatch(TwinCardsAction.SetResources(resources))
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
store.subscribe(this) { state ->
|
||||
|
|
@ -55,9 +67,7 @@ class CreateTwinWalletFragment : Fragment(R.layout.fragment_twin_cards_create),
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
toolbar.setNavigationOnClickListener {
|
||||
store.dispatch(TwinCardsAction.CreateWallet.Cancel)
|
||||
}
|
||||
toolbar.setNavigationOnClickListener { store.dispatch(TwinCardsAction.Wallet.HandleOnBackPressed) }
|
||||
|
||||
Picasso.get()
|
||||
.load(Artwork.TWIN_CARD_1)
|
||||
|
|
@ -96,12 +106,12 @@ class CreateTwinWalletFragment : Fragment(R.layout.fragment_twin_cards_create),
|
|||
v_step_2.setBackgroundColor(defaultColor)
|
||||
v_step_3.setBackgroundColor(defaultColor)
|
||||
btn_tap.setOnClickListener {
|
||||
store.dispatch(TwinCardsAction.CreateWallet.LaunchFirstStep(
|
||||
store.dispatch(TwinCardsAction.Wallet.LaunchFirstStep(
|
||||
Message(getString(
|
||||
R.string.details_twins_recreate_title_format,
|
||||
twinCardNumberString
|
||||
)),
|
||||
requireContext()
|
||||
assetReader
|
||||
))
|
||||
}
|
||||
btn_tap.text = getString(R.string.details_twins_recreate_button_format,
|
||||
|
|
@ -117,7 +127,7 @@ class CreateTwinWalletFragment : Fragment(R.layout.fragment_twin_cards_create),
|
|||
v_step_2.setBackgroundColor(selectedColor)
|
||||
v_step_3.setBackgroundColor(defaultColor)
|
||||
btn_tap.setOnClickListener {
|
||||
store.dispatch(TwinCardsAction.CreateWallet.LaunchSecondStep(
|
||||
store.dispatch(TwinCardsAction.Wallet.LaunchSecondStep(
|
||||
Message(getString(R.string.details_twins_recreate_title_format, twinCardNumberString)),
|
||||
Message(getString(R.string.details_twins_recreate_title_preparing)),
|
||||
Message(getString(R.string.details_twins_recreate_title_creating_wallet)),
|
||||
|
|
@ -135,7 +145,7 @@ class CreateTwinWalletFragment : Fragment(R.layout.fragment_twin_cards_create),
|
|||
v_step_2.setBackgroundColor(selectedColor)
|
||||
v_step_3.setBackgroundColor(selectedColor)
|
||||
btn_tap.setOnClickListener {
|
||||
store.dispatch(TwinCardsAction.CreateWallet.LaunchThirdStep(
|
||||
store.dispatch(TwinCardsAction.Wallet.LaunchThirdStep(
|
||||
Message(getString(
|
||||
R.string.details_twins_recreate_title_format, twinCardNumberString)
|
||||
)
|
||||
|
|
@ -148,27 +158,5 @@ class CreateTwinWalletFragment : Fragment(R.layout.fragment_twin_cards_create),
|
|||
}
|
||||
btn_tap.text = getString(R.string.details_twins_recreate_button_format, cardNumber)
|
||||
tv_twin_title.text = getString(R.string.details_twins_recreate_title_format, cardNumber)
|
||||
|
||||
if (state.createWalletState?.showAlert == true) {
|
||||
if (dialog == null) {
|
||||
dialog = MaterialAlertDialogBuilder(requireContext())
|
||||
.setMessage(R.string.details_twins_recreate_alert)
|
||||
.setPositiveButton(R.string.common_ok) { _, _ ->
|
||||
store.dispatch(TwinCardsAction.CreateWallet.Cancel.Confirm)
|
||||
}
|
||||
.setNegativeButton(R.string.common_cancel) { _, _ ->
|
||||
dialog?.cancel()
|
||||
}
|
||||
.setOnCancelListener {
|
||||
store.dispatch(TwinCardsAction.CreateWallet.HideAlert)
|
||||
}
|
||||
.create()
|
||||
dialog?.show()
|
||||
}
|
||||
} else {
|
||||
dialog?.cancel()
|
||||
dialog = null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -39,7 +39,7 @@ class TwinWalletWarningFragment : Fragment(R.layout.fragment_twin_cards_warning)
|
|||
}
|
||||
|
||||
btn_cancel.setOnClickListener { store.dispatch(NavigationAction.PopBackTo()) }
|
||||
btn_start.setOnClickListener { store.dispatch(TwinCardsAction.CreateWallet.Proceed) }
|
||||
btn_start.setOnClickListener { store.dispatch(TwinCardsAction.ProceedToCreateWallet) }
|
||||
Picasso.get()
|
||||
.load(Artwork.TWIN_CARD_1)
|
||||
.placeholder(R.drawable.card_placeholder)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
package com.tangem.tap.features.twins.ui.dialog
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.tangem.tap.common.extensions.dispatchDialogHide
|
||||
import com.tangem.tap.features.twins.redux.TwinCardsAction
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class CreateWalletInterruptDialog {
|
||||
companion object {
|
||||
fun create(state: TwinCardsAction.Wallet.InterruptDialog, context: Context): AlertDialog {
|
||||
return MaterialAlertDialogBuilder(context)
|
||||
.setMessage(R.string.details_twins_recreate_alert)
|
||||
.setPositiveButton(R.string.common_ok) { _, _ -> state.interrupt() }
|
||||
.setNegativeButton(R.string.common_cancel) { _, _ -> }
|
||||
.setOnDismissListener { store.dispatchDialogHide() }
|
||||
.create()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -65,5 +65,5 @@ fun Wallet.getPendingTransactions(): List<PendingTransaction> {
|
|||
}
|
||||
|
||||
fun Wallet.hasPendingTransactions(): Boolean {
|
||||
return recentTransactions.toPendingTransactions(address).isNotEmpty()
|
||||
return getPendingTransactions().isNotEmpty()
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ class WalletMiddleware {
|
|||
}
|
||||
is WalletAction.CreateWallet -> {
|
||||
if (walletState.isTangemTwins) {
|
||||
store.dispatch(TwinCardsAction.CreateWallet.Create(
|
||||
store.dispatch(TwinCardsAction.Wallet.Create(
|
||||
walletState.twinCardsState.cardNumber!!,
|
||||
CreateTwinWalletMode.CreateWallet
|
||||
))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue