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