Updated on 2026-08-14
This commit is contained in:
commit
53efbb730f
8 changed files with 107 additions and 0 deletions
|
|
@ -31,6 +31,7 @@ import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
|
|||
import com.tangem.operations.pins.CheckUserCodesCommand
|
||||
import com.tangem.operations.pins.CheckUserCodesResponse
|
||||
import com.tangem.operations.pins.SetUserCodeCommand
|
||||
import com.tangem.operations.usersetttings.SetUserCodeRecoveryAllowedTask
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
import com.tangem.tap.domain.tasks.CreateWalletAndRescanTask
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTask
|
||||
|
|
@ -173,6 +174,14 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co
|
|||
)
|
||||
}
|
||||
|
||||
suspend fun setAccessCodeRecoveryEnabled(cardId: String?, enabled: Boolean): CompletionResult<SuccessResponse> {
|
||||
return runTaskAsyncReturnOnMain(
|
||||
SetUserCodeRecoveryAllowedTask(enabled),
|
||||
cardId,
|
||||
initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun scanCard(
|
||||
cardId: String? = null,
|
||||
allowRequestAccessCodeFromRepository: Boolean = false,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,15 @@ sealed class DetailsAction : Action {
|
|||
data class PrepareCardSettingsData(val card: CardDTO, val cardTypesResolver: CardTypesResolver) : DetailsAction()
|
||||
object ResetCardSettingsData : DetailsAction()
|
||||
|
||||
sealed class AccessCodeRecovery : DetailsAction() {
|
||||
object Open : AccessCodeRecovery()
|
||||
data class SaveChanges(val enabled: Boolean) : AccessCodeRecovery() {
|
||||
data class Success(val enabled: Boolean) : AccessCodeRecovery()
|
||||
}
|
||||
|
||||
data class SelectOption(val enabled: Boolean) : AccessCodeRecovery()
|
||||
}
|
||||
|
||||
sealed class ManageSecurity : DetailsAction() {
|
||||
object OpenSecurity : ManageSecurity()
|
||||
data class SelectOption(val option: SecurityOption) : ManageSecurity()
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class DetailsMiddleware {
|
|||
private val eraseWalletMiddleware = EraseWalletMiddleware()
|
||||
private val manageSecurityMiddleware = ManageSecurityMiddleware()
|
||||
private val managePrivacyMiddleware = ManagePrivacyMiddleware()
|
||||
private val accessCodeRecoveryMiddleware = AccessCodeRecoveryMiddleware()
|
||||
val detailsMiddleware: Middleware<AppState> = { _, stateProvider ->
|
||||
{ next ->
|
||||
{ action ->
|
||||
|
|
@ -74,6 +75,7 @@ class DetailsMiddleware {
|
|||
store.dispatch(TwinCardsAction.SetMode(CreateTwinWalletMode.RecreateWallet))
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingTwins))
|
||||
}
|
||||
is DetailsAction.AccessCodeRecovery -> accessCodeRecoveryMiddleware.handle(state, action)
|
||||
DetailsAction.ScanCard -> {
|
||||
scope.launch {
|
||||
tangemSdkManager.scanProduct(
|
||||
|
|
@ -418,4 +420,28 @@ class DetailsMiddleware {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
class AccessCodeRecoveryMiddleware {
|
||||
fun handle(state: DetailsState, action: DetailsAction.AccessCodeRecovery) {
|
||||
when (action) {
|
||||
is DetailsAction.AccessCodeRecovery.Open -> {
|
||||
// store.dispatch(NavigationAction.NavigateTo(AppScreen.AccessCodeRecovery)) Todo: next PR
|
||||
}
|
||||
is DetailsAction.AccessCodeRecovery.SaveChanges -> {
|
||||
scope.launch {
|
||||
tangemSdkManager
|
||||
.setAccessCodeRecoveryEnabled(state.cardSettingsState?.card?.cardId, action.enabled)
|
||||
.doOnSuccess {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo())
|
||||
store.dispatchOnMain(
|
||||
DetailsAction.AccessCodeRecovery.SaveChanges.Success(action.enabled),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
is DetailsAction.AccessCodeRecovery.SelectOption -> Unit
|
||||
is DetailsAction.AccessCodeRecovery.SaveChanges.Success -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -40,6 +40,7 @@ private fun internalReduce(action: Action, state: AppState): DetailsState {
|
|||
}
|
||||
is DetailsAction.ChangeAppCurrency ->
|
||||
detailsState.copy(appCurrency = action.fiatCurrency)
|
||||
is DetailsAction.AccessCodeRecovery -> handleAccessCodeRecoveryAction(action, detailsState)
|
||||
else -> detailsState
|
||||
}
|
||||
}
|
||||
|
|
@ -68,6 +69,15 @@ private fun handlePrepareCardSettingsScreen(
|
|||
manageSecurityState = prepareSecurityOptions(card, cardTypesResolver),
|
||||
card = card,
|
||||
resetCardAllowed = isResetToFactoryAllowedByCard(card, cardTypesResolver),
|
||||
accessCodeRecovery = if (cardTypesResolver.isWallet2()) {
|
||||
val enabled = card.userSettings?.isUserCodeRecoveryAllowed ?: false
|
||||
AccessCodeRecoveryState(
|
||||
enabledOnCard = enabled,
|
||||
enabledSelection = enabled,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
)
|
||||
return state.copy(cardSettingsState = cardSettingsState)
|
||||
}
|
||||
|
|
@ -189,6 +199,34 @@ private fun handlePrivacyAction(action: DetailsAction.AppSettings, state: Detail
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleAccessCodeRecoveryAction(
|
||||
action: DetailsAction.AccessCodeRecovery,
|
||||
state: DetailsState,
|
||||
): DetailsState {
|
||||
return when (action) {
|
||||
DetailsAction.AccessCodeRecovery.Open -> {
|
||||
val accessCodeRecovery = state.cardSettingsState?.accessCodeRecovery?.copy(
|
||||
enabledSelection = state.cardSettingsState.accessCodeRecovery.enabledOnCard,
|
||||
)
|
||||
state.copy(cardSettingsState = state.cardSettingsState?.copy(accessCodeRecovery = accessCodeRecovery))
|
||||
}
|
||||
is DetailsAction.AccessCodeRecovery.SaveChanges -> state
|
||||
is DetailsAction.AccessCodeRecovery.SelectOption -> {
|
||||
val accessCodeRecovery = state.cardSettingsState?.accessCodeRecovery?.copy(
|
||||
enabledSelection = action.enabled,
|
||||
)
|
||||
state.copy(cardSettingsState = state.cardSettingsState?.copy(accessCodeRecovery = accessCodeRecovery))
|
||||
}
|
||||
is DetailsAction.AccessCodeRecovery.SaveChanges.Success -> {
|
||||
val accessCodeRecovery = state.cardSettingsState?.accessCodeRecovery?.copy(
|
||||
enabledOnCard = action.enabled,
|
||||
enabledSelection = action.enabled,
|
||||
)
|
||||
state.copy(cardSettingsState = state.cardSettingsState?.copy(accessCodeRecovery = accessCodeRecovery))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun prepareAllowedSecurityOptions(
|
||||
cardTypesResolver: CardTypesResolver,
|
||||
currentSecurityOption: SecurityOption?,
|
||||
|
|
|
|||
|
|
@ -26,12 +26,22 @@ data class CardInfo(
|
|||
val hasBackup: Boolean,
|
||||
)
|
||||
|
||||
/**
|
||||
* @property enabledOnCard whether access code recovery is enabled on card
|
||||
* @property enabledSelection current selected option in app (not saved on card yet)
|
||||
*/
|
||||
data class AccessCodeRecoveryState(
|
||||
val enabledOnCard: Boolean,
|
||||
val enabledSelection: Boolean,
|
||||
)
|
||||
|
||||
data class CardSettingsState(
|
||||
val cardInfo: CardInfo,
|
||||
val card: CardDTO,
|
||||
val manageSecurityState: ManageSecurityState?,
|
||||
val resetCardAllowed: Boolean,
|
||||
val resetConfirmed: Boolean = false,
|
||||
val accessCodeRecovery: AccessCodeRecoveryState? = null,
|
||||
)
|
||||
|
||||
data class ManageSecurityState(
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ data class CardDTO(
|
|||
val manufacturer: Manufacturer,
|
||||
val issuer: Issuer,
|
||||
val settings: Settings,
|
||||
val userSettings: UserSettings?,
|
||||
val linkedTerminalStatus: LinkedTerminalStatus,
|
||||
val isAccessCodeSet: Boolean,
|
||||
val isPasscodeSet: Boolean?,
|
||||
|
|
@ -39,6 +40,7 @@ data class CardDTO(
|
|||
manufacturer = Manufacturer(card.manufacturer),
|
||||
issuer = Issuer(card.issuer),
|
||||
settings = Settings(card.settings),
|
||||
userSettings = UserSettings(card.userSettings),
|
||||
linkedTerminalStatus = LinkedTerminalStatus.fromSdkStatus(card.linkedTerminalStatus),
|
||||
isAccessCodeSet = card.isAccessCodeSet,
|
||||
isPasscodeSet = card.isPasscodeSet,
|
||||
|
|
@ -60,6 +62,7 @@ data class CardDTO(
|
|||
if (manufacturer != other.manufacturer) return false
|
||||
if (issuer != other.issuer) return false
|
||||
if (settings != other.settings) return false
|
||||
if (userSettings != other.userSettings) return false
|
||||
if (linkedTerminalStatus != other.linkedTerminalStatus) return false
|
||||
if (isAccessCodeSet != other.isAccessCodeSet) return false
|
||||
if (isPasscodeSet != other.isPasscodeSet) return false
|
||||
|
|
@ -78,6 +81,7 @@ data class CardDTO(
|
|||
result = 31 * result + manufacturer.hashCode()
|
||||
result = 31 * result + issuer.hashCode()
|
||||
result = 31 * result + settings.hashCode()
|
||||
result = 31 * result + userSettings.hashCode()
|
||||
result = 31 * result + linkedTerminalStatus.hashCode()
|
||||
result = 31 * result + isAccessCodeSet.hashCode()
|
||||
result = 31 * result + (isPasscodeSet?.hashCode() ?: 0)
|
||||
|
|
@ -114,6 +118,15 @@ data class CardDTO(
|
|||
)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class UserSettings(
|
||||
val isUserCodeRecoveryAllowed: Boolean,
|
||||
) {
|
||||
constructor(userSettings: com.tangem.common.card.UserSettings) : this(
|
||||
userSettings.isUserCodeRecoveryAllowed,
|
||||
)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class FirmwareVersion(
|
||||
val major: Int,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.blockchain.common.Token
|
|||
interface CardTypesResolver {
|
||||
fun isTangemNote(): Boolean
|
||||
fun isTangemWallet(): Boolean
|
||||
fun isWallet2(): Boolean
|
||||
fun isSaltPay(): Boolean
|
||||
fun isSaltPayVisa(): Boolean
|
||||
fun isSaltPayWallet(): Boolean
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class TangemCardTypesResolver(
|
|||
card.firmwareVersion >= FirmwareVersion.MultiWalletAvailable &&
|
||||
!card.isSaltPay
|
||||
|
||||
override fun isWallet2(): Boolean = card.firmwareVersion >= FirmwareVersion.KeysImportAvailable
|
||||
override fun isSaltPay(): Boolean = productType == ProductType.SaltPay
|
||||
override fun isSaltPayVisa(): Boolean = card.isSaltPayVisa
|
||||
override fun isSaltPayWallet(): Boolean = card.isSaltPayWallet
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue