diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt index 114c17c7cd..a604cbd643 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -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 { 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 -> diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index 75e8333a1c..14f7b50b6b 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -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) diff --git a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt index df48e76971..39c203e744 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt @@ -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 { - val file = context.readAssetAsString("tangem-app-config/issuers") + private fun getIssuers(reader: AssetReader): List { + 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, diff --git a/app/src/main/java/com/tangem/tap/domain/twins/TwinsCardWidget.kt b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsWidget.kt similarity index 100% rename from app/src/main/java/com/tangem/tap/domain/twins/TwinsCardWidget.kt rename to app/src/main/java/com/tangem/tap/domain/twins/TwinCardsWidget.kt diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt index efa81149b7..31d11dbc31 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/DetailsFragment.kt @@ -95,7 +95,7 @@ class DetailsFragment : Fragment(R.layout.fragment_details), StoreSubscriber + 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)) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt index 6bf7ca96bf..173662c65e 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/OnboardingNoteFragment.kt @@ -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() { 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) } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteAction.kt index 798f8f4136..1948bfe98c 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteAction.kt @@ -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() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt index d4f1c2bcb7..33c5cbdd7d 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt @@ -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 -) \ No newline at end of file +data class OnboardingNoteResources( + val strings: Strings = Strings() +) { + data class Strings( + val addressWasCopied: Int = -1 + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsAction.kt b/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsAction.kt index cf7d2433dd..383481a905 100644 --- a/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsAction.kt +++ b/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsAction.kt @@ -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() } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsMiddleware.kt index 673e0616d5..84c837d778 100644 --- a/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsMiddleware.kt @@ -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 = { 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 -> { - - } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsReducer.kt b/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsReducer.kt index 6f9e3a6f57..89978790a1 100644 --- a/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsReducer.kt @@ -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 } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsState.kt b/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsState.kt index 49a43b9d93..f23ac31930 100644 --- a/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsState.kt +++ b/app/src/main/java/com/tangem/tap/features/twins/redux/TwinCardsState.kt @@ -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 + ) +} diff --git a/app/src/main/java/com/tangem/tap/features/twins/ui/CreateTwinWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/twins/ui/CreateTwinWalletFragment.kt index 0c23906aaf..94c5a099bc 100644 --- a/app/src/main/java/com/tangem/tap/features/twins/ui/CreateTwinWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/twins/ui/CreateTwinWalletFragment.kt @@ -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 { - 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 - } } - } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/twins/ui/TwinWalletWarningFragment.kt b/app/src/main/java/com/tangem/tap/features/twins/ui/TwinWalletWarningFragment.kt index fefff8729c..18f779a400 100644 --- a/app/src/main/java/com/tangem/tap/features/twins/ui/TwinWalletWarningFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/twins/ui/TwinWalletWarningFragment.kt @@ -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) diff --git a/app/src/main/java/com/tangem/tap/features/twins/ui/dialog/CreateWalletInterruptDialog.kt b/app/src/main/java/com/tangem/tap/features/twins/ui/dialog/CreateWalletInterruptDialog.kt new file mode 100644 index 0000000000..ab34b78039 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/twins/ui/dialog/CreateWalletInterruptDialog.kt @@ -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() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt index 492513e02c..29fe72df99 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt @@ -65,5 +65,5 @@ fun Wallet.getPendingTransactions(): List { } fun Wallet.hasPendingTransactions(): Boolean { - return recentTransactions.toPendingTransactions(address).isNotEmpty() + return getPendingTransactions().isNotEmpty() } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 61b4423e33..bdf79de67a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -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 ))