diff --git a/.idea/dictionaries/romanpotapov.xml b/.idea/dictionaries/romanpotapov.xml index 22eae8bc66..9973a9778a 100644 --- a/.idea/dictionaries/romanpotapov.xml +++ b/.idea/dictionaries/romanpotapov.xml @@ -2,6 +2,7 @@ blockchain + passcode tangem diff --git a/app/src/main/java/com/tangem/tap/common/entities/Button.kt b/app/src/main/java/com/tangem/tap/common/entities/Button.kt index 14383c3c99..986a170564 100644 --- a/app/src/main/java/com/tangem/tap/common/entities/Button.kt +++ b/app/src/main/java/com/tangem/tap/common/entities/Button.kt @@ -1,3 +1,3 @@ package com.tangem.tap.common.entities -abstract class Button(val enabled: Boolean) \ No newline at end of file +open class Button(val enabled: Boolean) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt index bd8de9b6be..03246d0461 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt @@ -6,6 +6,7 @@ import androidx.fragment.app.FragmentManager import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.features.details.ui.DetailsConfirmFragment import com.tangem.tap.features.details.ui.DetailsFragment +import com.tangem.tap.features.details.ui.DetailsSecurityFragment import com.tangem.tap.features.home.HomeFragment import com.tangem.tap.features.send.ui.SendFragment import com.tangem.tap.features.wallet.ui.WalletFragment @@ -40,5 +41,6 @@ private fun fragmentFactory(screen: AppScreen): Fragment { AppScreen.Send -> SendFragment() AppScreen.Details -> DetailsFragment() AppScreen.DetailsConfirm -> DetailsConfirmFragment() + AppScreen.DetailsSecurity -> DetailsSecurityFragment() } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationState.kt b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationState.kt index 60dba22fbc..3a062653d8 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationState.kt @@ -9,4 +9,4 @@ data class NavigationState( val activity: WeakReference? = null ) : StateType -enum class AppScreen { Home, Wallet, Send, Details, DetailsConfirm } \ No newline at end of file +enum class AppScreen { Home, Wallet, Send, Details, DetailsConfirm, DetailsSecurity } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt index 3c9b613d01..38dcfe6358 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt @@ -2,11 +2,10 @@ package com.tangem.tap.domain import androidx.activity.ComponentActivity import com.tangem.* -import com.tangem.commands.CommandResponse -import com.tangem.commands.PurgeWalletCommand -import com.tangem.commands.PurgeWalletResponse +import com.tangem.commands.* import com.tangem.common.CompletionResult import com.tangem.common.extensions.CardType +import com.tangem.common.extensions.calculateSha256 import com.tangem.tangem_sdk_new.extensions.init import com.tangem.tap.domain.tasks.CreateWalletAndRescanTask import com.tangem.tap.domain.tasks.ScanNoteResponse @@ -26,12 +25,28 @@ class TangemSdkManager(val activity: ComponentActivity) { return runTaskAsyncReturnOnMain(ScanNoteTask()) } - suspend fun createWallet(): CompletionResult { - return runTaskAsyncReturnOnMain(CreateWalletAndRescanTask()) + suspend fun createWallet(cardId: String?): CompletionResult { + return runTaskAsyncReturnOnMain(CreateWalletAndRescanTask(), cardId) } - suspend fun eraseWallet(): CompletionResult { - return runTaskAsyncReturnOnMain(PurgeWalletCommand()) + suspend fun eraseWallet(cardId: String?): CompletionResult { + return runTaskAsyncReturnOnMain(PurgeWalletCommand(), cardId) + } + + suspend fun setPasscode(cardId: String?): CompletionResult { + return runTaskAsyncReturnOnMain(SetPinCommand.setPin1(null), cardId) + } + + suspend fun setAccessCode(cardId: String?): CompletionResult { + return runTaskAsyncReturnOnMain(SetPinCommand.setPin2(null), cardId) + } + + suspend fun setLongTap(cardId: String?): CompletionResult { + return runTaskAsyncReturnOnMain(SetPinCommand( + pinType = PinType.Pin1, + newPin1 = tangemSdk.config.defaultPin1.calculateSha256(), + newPin2 = tangemSdk.config.defaultPin2.calculateSha256() + ), cardId) } private suspend fun runTaskAsync( diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt index bddb0b3d6c..1b3d174176 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt @@ -41,4 +41,18 @@ sealed class DetailsAction : Action { data class SelectAppCurrency(val fiatCurrencyName: FiatCurrencyName): AppCurrencyAction() } + sealed class ManageSecurity : DetailsAction() { + object OpenSecurity : ManageSecurity() + data class SelectOption(val option: SecurityOption) : ManageSecurity() + object SaveChanges : ManageSecurity() { + object Success : ManageSecurity() + object Failure : ManageSecurity() + } + data class ConfirmSelection(val option: SecurityOption) : ManageSecurity() { + object AlreadySet: ManageSecurity(), NotificationAction { + override val messageResource = R.string.details_notification_security_option_already_active + } + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index 50a0d1d452..1376dd5398 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -18,64 +18,127 @@ import kotlinx.coroutines.withContext import org.rekotlin.Middleware class DetailsMiddleware { + private val eraseWalletMiddleware = EraseWalletMiddleware() + private val appCurrencyMiddleware = AppCurrencyMiddleware() + private val manageSecurityMiddleware = ManageSecurityMiddleware() val detailsMiddleware: Middleware = { dispatch, state -> { next -> { action -> when (action) { - is DetailsAction.PrepareScreen -> { - scope.launch { - val loadedCurrencies = preferencesStorage.getFiatCurrencies() - if (loadedCurrencies.isNullOrEmpty()) { - val response = CoinMarketCapService().getFiatCurrencies() - withContext(Dispatchers.Main) { - when (response) { - is Result.Success -> { - preferencesStorage.saveFiatCurrencies(response.data) - store.dispatch(DetailsAction.AppCurrencyAction.SetCurrencies(response.data)) - } - } - } - } else { - withContext(Dispatchers.Main) { - store.dispatch(DetailsAction.AppCurrencyAction.SetCurrencies(loadedCurrencies)) - } - } - } - - } - is DetailsAction.EraseWallet.Proceed -> { - when (store.state.detailsState.eraseWalletState) { - EraseWalletState.Allowed -> - store.dispatch(NavigationAction.NavigateTo(AppScreen.DetailsConfirm)) - EraseWalletState.NotAllowedByCard -> - store.dispatch(DetailsAction.EraseWallet.Proceed.NotAllowedByCard) - EraseWalletState.NotEmpty -> - store.dispatch(DetailsAction.EraseWallet.Proceed.NotEmpty) - } - } - is DetailsAction.EraseWallet.Cancel -> { - store.dispatch(NavigationAction.PopBackTo()) - } - is DetailsAction.EraseWallet.Confirm -> { - scope.launch { - val result = tangemSdkManager.eraseWallet() - withContext(Dispatchers.Main) { - when (result) { - is CompletionResult.Success -> { - store.dispatch(NavigationAction.PopBackTo(AppScreen.Home)) - } - } - } - } - } - is DetailsAction.AppCurrencyAction.SelectAppCurrency -> { - preferencesStorage.saveAppCurrency(action.fiatCurrencyName) - store.dispatch(GlobalAction.ChangeAppCurrency(action.fiatCurrencyName)) - store.dispatch(WalletAction.LoadFiatRate) - } + is DetailsAction.PrepareScreen -> prepareData() + is DetailsAction.EraseWallet -> eraseWalletMiddleware.handle(action) + is DetailsAction.AppCurrencyAction -> appCurrencyMiddleware.handle(action) + is DetailsAction.ManageSecurity -> manageSecurityMiddleware.handle(action) } next(action) } } } + + private fun prepareData() { + scope.launch { + val loadedCurrencies = preferencesStorage.getFiatCurrencies() + if (loadedCurrencies.isNullOrEmpty()) { + val response = CoinMarketCapService().getFiatCurrencies() + withContext(Dispatchers.Main) { + when (response) { + is Result.Success -> { + preferencesStorage.saveFiatCurrencies(response.data) + store.dispatch(DetailsAction.AppCurrencyAction.SetCurrencies(response.data)) + } + } + } + } else { + withContext(Dispatchers.Main) { + store.dispatch(DetailsAction.AppCurrencyAction.SetCurrencies(loadedCurrencies)) + } + } + } + } + + class EraseWalletMiddleware() { + fun handle(action: DetailsAction.EraseWallet) { + when (action) { + is DetailsAction.EraseWallet.Proceed -> { + when (store.state.detailsState.eraseWalletState) { + EraseWalletState.Allowed -> + store.dispatch(NavigationAction.NavigateTo(AppScreen.DetailsConfirm)) + EraseWalletState.NotAllowedByCard -> + store.dispatch(DetailsAction.EraseWallet.Proceed.NotAllowedByCard) + EraseWalletState.NotEmpty -> + store.dispatch(DetailsAction.EraseWallet.Proceed.NotEmpty) + } + } + is DetailsAction.EraseWallet.Cancel -> { + store.dispatch(NavigationAction.PopBackTo()) + } + is DetailsAction.EraseWallet.Confirm -> { + scope.launch { + val result = tangemSdkManager.eraseWallet( + store.state.detailsState.card?.cardId + ) + withContext(Dispatchers.Main) { + when (result) { + is CompletionResult.Success -> { + store.dispatch(NavigationAction.PopBackTo(AppScreen.Home)) + } + } + } + } + } + } + } + } + + class AppCurrencyMiddleware { + fun handle(action: DetailsAction.AppCurrencyAction) { + when (action) { + is DetailsAction.AppCurrencyAction.SelectAppCurrency -> { + preferencesStorage.saveAppCurrency(action.fiatCurrencyName) + store.dispatch(GlobalAction.ChangeAppCurrency(action.fiatCurrencyName)) + store.dispatch(WalletAction.LoadFiatRate) + } + } + } + } + + class ManageSecurityMiddleware { + fun handle(action: DetailsAction.ManageSecurity) { + when (action) { + is DetailsAction.ManageSecurity.OpenSecurity -> { + store.dispatch(NavigationAction.NavigateTo(AppScreen.DetailsSecurity)) + } + is DetailsAction.ManageSecurity.ConfirmSelection -> { + if (action.option != store.state.detailsState.securityScreenState?.currentOption) { + store.dispatch(NavigationAction.NavigateTo(AppScreen.DetailsConfirm)) + } else { + store.dispatch(DetailsAction.ManageSecurity.ConfirmSelection.AlreadySet) + } + } + is DetailsAction.ManageSecurity.SaveChanges -> { + val cardId = store.state.detailsState.card?.cardId + scope.launch { + val result = when (store.state.detailsState.securityScreenState?.selectedOption) { + SecurityOption.LongTap -> tangemSdkManager.setLongTap(cardId) + SecurityOption.PassCode -> tangemSdkManager.setPasscode(cardId) + SecurityOption.AccessCode -> tangemSdkManager.setAccessCode(cardId) + else -> null + } + withContext(Dispatchers.Main) { + when (result) { + is CompletionResult.Success -> { + store.dispatch(NavigationAction.PopBackTo()) + store.dispatch(DetailsAction.ManageSecurity.SaveChanges.Success) + } + is CompletionResult.Failure, null -> + store.dispatch(DetailsAction.ManageSecurity.SaveChanges.Failure) + } + } + + } + + } + } + } + } } diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt index 9cc2fbb831..0f9cbff975 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt @@ -5,6 +5,7 @@ import com.tangem.commands.Settings import com.tangem.common.extensions.isZero import com.tangem.tap.common.redux.AppState import org.rekotlin.Action +import java.util.* class DetailsReducer { companion object { @@ -13,28 +14,45 @@ class DetailsReducer { } private fun internalReduce(action: Action, state: AppState): DetailsState { - if (action !is DetailsAction) return state.detailsState - var detailsState = state.detailsState - when (action) { + val detailsState = state.detailsState + return when (action) { is DetailsAction.PrepareScreen -> { - detailsState = DetailsState( - card = action.card, wallet = action.wallet, - cardInfo = action.card.toCardInfo(), - appCurrencyState = AppCurrencyState( - action.fiatCurrencyName - ) - ) + handlePrepareScreen(action, detailsState) } is DetailsAction.EraseWallet -> { - detailsState = handleEraseWallet(action, detailsState) + handleEraseWallet(action, detailsState) } is DetailsAction.AppCurrencyAction -> { - detailsState = handleAppCurrencyAction(action, detailsState) + handleAppCurrencyAction(action, detailsState) + } + is DetailsAction.ManageSecurity -> { + handleSecurityAction(action, detailsState) } } - return detailsState +} + +private fun handlePrepareScreen(action: DetailsAction.PrepareScreen, state: DetailsState): DetailsState { + val securityOption = when { + action.card.isPin1Default == false -> { + SecurityOption.AccessCode + } + action.card.isPin2Default == false -> { + SecurityOption.PassCode + } + else -> { + SecurityOption.LongTap + } + } + return DetailsState( + card = action.card, wallet = action.wallet, + cardInfo = action.card.toCardInfo(), + appCurrencyState = AppCurrencyState( + action.fiatCurrencyName + ), + securityScreenState = SecurityScreenState(currentOption = securityOption) + ) } private fun handleEraseWallet(action: DetailsAction.EraseWallet, state: DetailsState): DetailsState { @@ -88,6 +106,55 @@ private fun handleAppCurrencyAction( } } +private fun handleSecurityAction( + action: DetailsAction.ManageSecurity, state: DetailsState +): DetailsState { + return when (action) { + is DetailsAction.ManageSecurity.OpenSecurity -> { + 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.AccessCode) + } + + state.copy(securityScreenState = state.securityScreenState?.copy( + allowedOptions = allowedSecurityOptions + )) + } + is DetailsAction.ManageSecurity.SelectOption -> { + state.copy(securityScreenState = state.securityScreenState?.copy( + selectedOption = action.option + )) + } + is DetailsAction.ManageSecurity.ConfirmSelection -> { + val confirmScreenState = when (action.option) { + SecurityOption.LongTap -> ConfirmScreenState.LongTap + SecurityOption.PassCode -> ConfirmScreenState.PassCode + SecurityOption.AccessCode -> ConfirmScreenState.AccessCode + } + state.copy(confirmScreenState = confirmScreenState) + } + is DetailsAction.ManageSecurity.SaveChanges.Success -> { + state.copy(securityScreenState = state.securityScreenState?.copy( + currentOption = state.securityScreenState.selectedOption + )) + } + + else -> state + } +} + private fun Card.toCardInfo(): CardInfo? { val cardId = this.cardId.chunked(4).joinToString(separator = " ") val issuer = this.cardData?.issuerName ?: return null diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsState.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsState.kt index 304e7902c8..7c152c57ee 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsState.kt @@ -2,10 +2,12 @@ package com.tangem.tap.features.details.redux import com.tangem.blockchain.common.Wallet import com.tangem.commands.Card +import com.tangem.tap.common.entities.Button import com.tangem.tap.common.entities.TapCurrency.Companion.DEFAULT_FIAT_CURRENCY import com.tangem.tap.common.redux.global.FiatCurrencyName import com.tangem.tap.network.coinmarketcap.FiatCurrency import org.rekotlin.StateType +import java.util.* data class DetailsState( val card: Card? = null, @@ -14,6 +16,7 @@ data class DetailsState( val appCurrencyState: AppCurrencyState = AppCurrencyState(), val eraseWalletState: EraseWalletState? = null, val confirmScreenState: ConfirmScreenState? = null, + val securityScreenState: SecurityScreenState? = null, ) : StateType data class CardInfo( @@ -24,6 +27,14 @@ data class CardInfo( enum class EraseWalletState { Allowed, NotAllowedByCard, NotEmpty } enum class ConfirmScreenState { EraseWallet, LongTap, AccessCode, PassCode } +data class SecurityScreenState( + val currentOption: SecurityOption = SecurityOption.LongTap, + val selectedOption: SecurityOption = currentOption, + val allowedOptions: EnumSet = EnumSet.allOf(SecurityOption::class.java), + val buttonProceed: Button = Button(true) +) + +enum class SecurityOption { LongTap, PassCode, AccessCode } data class AppCurrencyState( val fiatCurrencyName: FiatCurrencyName = DEFAULT_FIAT_CURRENCY, val showAppCurrencyDialog: Boolean = false, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/DetailsConfirmFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/DetailsConfirmFragment.kt index a13937adbf..d75799b5c1 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/DetailsConfirmFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/DetailsConfirmFragment.kt @@ -59,16 +59,23 @@ class DetailsConfirmFragment : Fragment(R.layout.fragment_details_confirm), when (state.confirmScreenState) { ConfirmScreenState.EraseWallet -> { toolbar.title = getString(R.string.details_erase_wallet) + tv_warning_description.text = getString(R.string.details_erase_wallet_warning) btn_confirm.text = getString(R.string.details_erase_wallet) btn_confirm.setCompoundDrawablesRelativeWithIntrinsicBounds( null, null, getDrawable(R.drawable.ic_send), null ) btn_confirm.setOnClickListener { store.dispatch(DetailsAction.EraseWallet.Confirm) } } - ConfirmScreenState.LongTap -> TODO() - ConfirmScreenState.AccessCode -> TODO() - ConfirmScreenState.PassCode -> TODO() - null -> TODO() + ConfirmScreenState.LongTap, ConfirmScreenState.AccessCode, + ConfirmScreenState.PassCode -> { + toolbar.title = getString(R.string.details_manage_security) + tv_warning_description.text = getString(R.string.details_manage_security_warning) + btn_confirm.text = getString(R.string.details_save_changes) + btn_confirm.setCompoundDrawablesRelativeWithIntrinsicBounds( + null, null, getDrawable(R.drawable.ic_save), null + ) + btn_confirm.setOnClickListener { store.dispatch(DetailsAction.ManageSecurity.SaveChanges) } + } } 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 eeca408c37..f4bdf9519a 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 @@ -8,6 +8,7 @@ import androidx.transition.TransitionInflater import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.details.redux.DetailsState +import com.tangem.tap.features.details.redux.SecurityOption import com.tangem.tap.store import com.tangem.wallet.R import kotlinx.android.synthetic.main.fragment_details.* @@ -74,6 +75,18 @@ class DetailsFragment : Fragment(R.layout.fragment_details), StoreSubscriber R.string.details_manage_security_long_tap + SecurityOption.PassCode -> R.string.details_manage_security_passcode + SecurityOption.AccessCode -> R.string.details_manage_security_access_code + null -> null + } + currentSecurity?.let { tv_security.text = getString(it) } + if (state.appCurrencyState.showAppCurrencyDialog && !state.appCurrencyState.fiatCurrencies.isNullOrEmpty()) { currencySelectionDialog.show( diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/DetailsSecurityFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/DetailsSecurityFragment.kt new file mode 100644 index 0000000000..60050df949 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/DetailsSecurityFragment.kt @@ -0,0 +1,83 @@ +package com.tangem.tap.features.details.ui + +import android.os.Bundle +import android.view.View +import androidx.activity.OnBackPressedCallback +import androidx.fragment.app.Fragment +import androidx.transition.TransitionInflater +import com.tangem.tap.common.redux.navigation.NavigationAction +import com.tangem.tap.features.details.redux.DetailsAction +import com.tangem.tap.features.details.redux.DetailsState +import com.tangem.tap.features.details.redux.SecurityOption +import com.tangem.tap.store +import com.tangem.wallet.R +import kotlinx.android.synthetic.main.fragment_details_confirm.toolbar +import kotlinx.android.synthetic.main.fragment_details_security.* +import org.rekotlin.StoreSubscriber + +class DetailsSecurityFragment : Fragment(R.layout.fragment_details_security), + StoreSubscriber { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + store.dispatch(NavigationAction.PopBackTo()) + } + }) + val inflater = TransitionInflater.from(requireContext()) + enterTransition = inflater.inflateTransition(R.transition.slide_right) + exitTransition = inflater.inflateTransition(R.transition.fade) + } + + override fun onStart() { + super.onStart() + store.subscribe(this) { state -> + state.skipRepeats { oldState, newState -> + oldState.detailsState == newState.detailsState + }.select { it.detailsState } + } + } + + override fun onStop() { + super.onStop() + store.unsubscribe(this) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + toolbar.setNavigationOnClickListener { + store.dispatch(NavigationAction.PopBackTo()) + } + setOnClickListeners() + } + + private fun setOnClickListeners() { + v_long_tap.setOnClickListener { + store.dispatch(DetailsAction.ManageSecurity.SelectOption(SecurityOption.LongTap)) + } + v_passcode.setOnClickListener { + store.dispatch(DetailsAction.ManageSecurity.SelectOption(SecurityOption.PassCode)) + } + v_access_code.setOnClickListener { + store.dispatch(DetailsAction.ManageSecurity.SelectOption(SecurityOption.AccessCode)) + } + btn_save_changes.setOnClickListener { + store.state.detailsState.securityScreenState?.selectedOption?.let { + store.dispatch(DetailsAction.ManageSecurity.ConfirmSelection(it)) + } + } + } + + override fun newState(state: DetailsState) { + if (activity == null) return + selectSecurityOption(state.securityScreenState?.selectedOption) + } + + private fun selectSecurityOption(securityOption: SecurityOption?) { + radiobutton_long_tap.isChecked = securityOption == SecurityOption.LongTap + radiobutton_passcode.isChecked = securityOption == SecurityOption.PassCode + radiobutton_access_code.isChecked = securityOption == SecurityOption.AccessCode + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletMiddleware.kt index 6c9f2b85bd..f6354b7291 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletMiddleware.kt @@ -63,7 +63,9 @@ val walletMiddleware: Middleware = { dispatch, state -> } is WalletAction.CreateWallet -> { scope.launch { - val result = tangemSdkManager.createWallet() + val result = tangemSdkManager.createWallet( + store.state.globalState.scanNoteResponse?.card?.cardId + ) when (result) { is CompletionResult.Success -> { store.state.globalState.tapWalletManager.onCardScanned(result.data) diff --git a/app/src/main/res/drawable/ic_save.xml b/app/src/main/res/drawable/ic_save.xml new file mode 100644 index 0000000000..756c7557dc --- /dev/null +++ b/app/src/main/res/drawable/ic_save.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/fragment_details_confirm.xml b/app/src/main/res/layout/fragment_details_confirm.xml index 528dc0aa4c..8aaec159c0 100644 --- a/app/src/main/res/layout/fragment_details_confirm.xml +++ b/app/src/main/res/layout/fragment_details_confirm.xml @@ -68,34 +68,27 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> - + app:layout_constraintGuide_percent="0.37" /> + app:layout_constraintBottom_toBottomOf="parent" /> diff --git a/app/src/main/res/layout/fragment_details_security.xml b/app/src/main/res/layout/fragment_details_security.xml new file mode 100644 index 0000000000..e645ea6b3b --- /dev/null +++ b/app/src/main/res/layout/fragment_details_security.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 22a73a85d7..5ebb9b3051 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -86,6 +86,7 @@ Details Card settings prohibits from erasing wallet You balance on this wallet is not zero, or you have unconfirmed transactions + This is the currently active option Card ID Issuer Signed @@ -95,6 +96,13 @@ Validate card Manage security Erase wallet + Save changes + Long Tap + Passcode + Access Code + This action is irreversible. If, after deleting the wallet, someone sends funds to it, then you will not be able to withdraw them. + If you forget the code, you will lose the ability to use the card. There is no way to recover or change your code if you lose it. + \ No newline at end of file