Updated on 2026-08-14

This commit is contained in:
Tangem 2022-10-25 14:30:23 +03:00
commit 92d6e94e11
25 changed files with 318 additions and 1567 deletions

File diff suppressed because it is too large Load diff

View file

@ -3,10 +3,10 @@ package com.tangem.tap.domain.moduleMessage.saltPay
import android.content.Context
import com.tangem.common.module.ModuleMessageConverter
import com.tangem.tap.domain.moduleMessage.ConvertedMessage
import com.tangem.tap.domain.moduleMessage.saltPay.converter.SaltPayRegistrationErrorConverter
import com.tangem.tap.domain.moduleMessage.saltPay.converter.SaltPayActivationErrorConverter
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayModuleError
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayModuleMessage
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
/**
[REDACTED_AUTHOR]
@ -28,7 +28,7 @@ class SaltPayErrorConverter(
) : ModuleMessageConverter<SaltPayModuleError, ConvertedMessage?> {
override fun convert(message: SaltPayModuleError): ConvertedMessage? = when (message) {
is SaltPayRegistrationError -> SaltPayRegistrationErrorConverter(context).convert(message)
is SaltPayActivationError -> SaltPayActivationErrorConverter(context).convert(message)
else -> null
}
}

View file

@ -3,40 +3,40 @@ package com.tangem.tap.domain.moduleMessage.saltPay.converter
import android.content.Context
import com.tangem.common.module.ModuleMessageConverter
import com.tangem.tap.domain.moduleMessage.ConvertedDialogMessage
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
import com.tangem.wallet.R
/**
[REDACTED_AUTHOR]
*/
internal class SaltPayRegistrationErrorConverter(
internal class SaltPayActivationErrorConverter(
private val context: Context,
) : ModuleMessageConverter<SaltPayRegistrationError, ConvertedDialogMessage?> {
) : ModuleMessageConverter<SaltPayActivationError, ConvertedDialogMessage?> {
override fun convert(message: SaltPayRegistrationError): ConvertedDialogMessage? {
val saltPayError = (message as? SaltPayRegistrationError) ?: throw UnsupportedOperationException()
override fun convert(message: SaltPayActivationError): ConvertedDialogMessage? {
val saltPayError = (message as? SaltPayActivationError) ?: throw UnsupportedOperationException()
val dialogMessage = when (saltPayError) {
SaltPayRegistrationError.NoGas -> {
SaltPayActivationError.NoGas -> {
ConvertedDialogMessage(
title = context.getString(R.string.saltpay_error_no_gas_title),
message = context.getString(R.string.saltpay_error_no_gas_message),
)
}
SaltPayRegistrationError.EmptyBackupCardScanned -> {
SaltPayActivationError.EmptyBackupCardScanned -> {
ConvertedDialogMessage(
title = context.getString(R.string.saltpay_error_empty_backup_title),
message = context.getString(R.string.saltpay_error_empty_backup_message),
)
}
SaltPayRegistrationError.WeakPin -> {
SaltPayActivationError.WeakPin -> {
ConvertedDialogMessage(
title = context.getString(R.string.saltpay_error_pin_weak_title),
message = context.getString(R.string.saltpay_error_pin_weak_message),
)
}
else -> {
val errorMessage = if (saltPayError.message == SaltPayRegistrationError.EMPTY_MESSAGE) {
val errorMessage = if (saltPayError.message == SaltPayActivationError.EMPTY_MESSAGE) {
saltPayError::class.java.simpleName
} else {
saltPayError.message

View file

@ -78,8 +78,7 @@ class DetailsViewModel(private val store: Store<AppState>) {
store.dispatch(DetailsAction.CreateBackup)
}
SettingsElement.TermsOfService -> {
store.dispatch(DisclaimerAction.ShowAcceptedDisclaimer)
store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer))
store.dispatch(DisclaimerAction.Show())
}
SettingsElement.TermsOfUse -> {
store.dispatch(DetailsAction.ShowDisclaimer)

View file

@ -1,8 +1,17 @@
package com.tangem.tap.features.disclaimer.redux
import com.tangem.common.extensions.VoidCallback
import org.rekotlin.Action
sealed class DisclaimerAction: Action {
object AcceptDisclaimer : DisclaimerAction()
object ShowAcceptedDisclaimer : DisclaimerAction()
sealed class DisclaimerAction : Action {
data class SetDisclaimerType(
val type: DisclaimerType,
) : DisclaimerAction()
data class Show(val onAcceptCallback: VoidCallback? = null) : DisclaimerAction()
data class AcceptDisclaimer(val type: DisclaimerType) : DisclaimerAction()
internal data class UpdateState(val type: DisclaimerType, val accepted: Boolean) : DisclaimerAction()
internal data class SetOnAcceptCallback(val onAcceptCallback: VoidCallback? = null) : DisclaimerAction()
}

View file

@ -1,28 +1,65 @@
package com.tangem.tap.features.disclaimer.redux
import com.tangem.tap.common.post
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.features.home.redux.HomeAction
import com.tangem.tap.preferencesStorage
import com.tangem.tap.store
import org.rekotlin.Action
import org.rekotlin.Middleware
class DisclaimerMiddleware {
val disclaimerMiddleware: Middleware<AppState> = { dispatch, state ->
{ next ->
{ action ->
when (action) {
is DisclaimerAction.AcceptDisclaimer -> {
preferencesStorage.saveDisclaimerAccepted()
store.dispatch(NavigationAction.PopBackTo())
//delayed sending used for better animation
post(550) { store.dispatch(HomeAction.ReadCard) }
}
}
state()?.let { handleDisclaimerMiddleware(action, it) }
next(action)
}
}
}
}
}
private fun handleDisclaimerMiddleware(action: Action, appState: AppState) {
val state = appState.disclaimerState
when (action) {
is DisclaimerAction.SetDisclaimerType -> {
handleUpdateState = action.type.createUpdateState()
}
is DisclaimerAction.Show -> {
handleUpdateState = state.type.createUpdateState()
store.dispatch(DisclaimerAction.SetOnAcceptCallback(action.onAcceptCallback))
store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer))
}
is DisclaimerAction.AcceptDisclaimer -> {
action.type.accept()
handleUpdateState = action.type.createUpdateState()
store.dispatch(NavigationAction.PopBackTo())
state.onAcceptCallback?.invoke()
store.dispatch(DisclaimerAction.SetOnAcceptCallback(null))
}
}
}
private fun DisclaimerType.accept() = when (this) {
DisclaimerType.SaltPay -> preferencesStorage.disclaimerPrefStorage.hasSaltPayTosAccepted = true
DisclaimerType.Tangem -> preferencesStorage.disclaimerPrefStorage.hasTangemTosAccepted = true
}
fun DisclaimerType.isAccepted(): Boolean = when (this) {
DisclaimerType.SaltPay -> preferencesStorage.disclaimerPrefStorage.hasSaltPayTosAccepted
DisclaimerType.Tangem -> preferencesStorage.disclaimerPrefStorage.hasTangemTosAccepted
}
private fun DisclaimerType.createUpdateState(): DisclaimerAction.UpdateState {
return DisclaimerAction.UpdateState(this, this.isAccepted())
}
private var handleUpdateState: DisclaimerAction.UpdateState = DisclaimerAction.UpdateState(
type = DisclaimerType.Tangem,
accepted = false,
)
set(value) {
field = value
store.dispatch(value)
}

View file

@ -13,9 +13,15 @@ private fun internalReduce(action: Action, state: AppState): DisclaimerState {
if (action !is DisclaimerAction) return state.disclaimerState
val disclaimerState = state.disclaimerState
return when (action) {
is DisclaimerAction.AcceptDisclaimer, DisclaimerAction.ShowAcceptedDisclaimer -> {
disclaimerState.copy(accepted = true)
}
is DisclaimerAction.UpdateState -> disclaimerState.copy(
type = action.type,
accepted = action.accepted,
)
is DisclaimerAction.SetOnAcceptCallback -> disclaimerState.copy(
onAcceptCallback = action.onAcceptCallback,
)
else -> disclaimerState
}
}

View file

@ -1,7 +1,30 @@
package com.tangem.tap.features.disclaimer.redux
import android.net.Uri
import com.tangem.common.card.Card
import com.tangem.common.extensions.VoidCallback
import com.tangem.domain.common.ScanResponse
import com.tangem.domain.common.TapWorkarounds.isSaltPay
import org.rekotlin.StateType
data class DisclaimerState(
val accepted: Boolean = false
val accepted: Boolean = false,
val type: DisclaimerType = DisclaimerType.Tangem,
val onAcceptCallback: VoidCallback? = null,
) : StateType
sealed class DisclaimerType(
val uri: Uri,
) {
object Tangem : DisclaimerType(Uri.parse("https://tangem.com/tangem_tos.html"))
object SaltPay : DisclaimerType(Uri.parse("https://tangem.com/soltpay_tos.html"))
companion object {
fun get(scanResponse: ScanResponse): DisclaimerType = get(scanResponse.card)
fun get(card: Card): DisclaimerType = when {
card.isSaltPay -> SaltPay
else -> Tangem
}
}
}

View file

@ -55,25 +55,25 @@ class DisclaimerFragment : Fragment(R.layout.fragment_disclaimer),
binding.toolbar.setNavigationOnClickListener {
store.dispatch(NavigationAction.PopBackTo())
}
initAndLoadTOS()
setOnClickListeners()
initViews()
}
private fun initAndLoadTOS() {
private fun initViews() {
binding.webView.configureSettings()
binding.webView.loadUrl("file:///android_asset/tos.html")
}
private fun setOnClickListeners() {
binding.btnAccept.setOnClickListener { store.dispatch(DisclaimerAction.AcceptDisclaimer) }
}
override fun newState(state: DisclaimerState) {
override fun newState(state: DisclaimerState) = with(binding) {
if (activity == null || view == null) return
if (state.accepted) {
binding.halfTransparentOverlay.hide()
binding.btnAccept.hide()
halfTransparentOverlay.hide()
btnAccept.hide()
}
btnAccept.setOnClickListener {
store.dispatch(DisclaimerAction.AcceptDisclaimer(state.type))
}
webView.loadUrl(state.type.uri.toString())
}
}

View file

@ -13,6 +13,5 @@ sealed class HomeAction : Action {
data class ShouldScanCardOnResume(val shouldScanCard: Boolean) : HomeAction()
object Init : HomeAction()
data class SetTermsOfUseState(val isDisclaimerAccepted: Boolean) : HomeAction()
data class ChangeScanCardButtonState(val state: IndeterminateProgressButton) : HomeAction()
}

View file

@ -20,6 +20,9 @@ import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.FragmentShareTransition
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
import com.tangem.tap.features.disclaimer.redux.DisclaimerType
import com.tangem.tap.features.disclaimer.redux.isAccepted
import com.tangem.tap.features.home.BELARUS_COUNTRY_CODE
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
import com.tangem.tap.features.home.redux.HomeMiddleware.Companion.BUY_WALLET_URL
@ -63,7 +66,6 @@ private fun handleHomeAction(appState: () -> AppState?, action: Action, dispatch
is HomeAction.Init -> {
store.dispatch(GlobalAction.RestoreAppCurrency)
store.dispatch(GlobalAction.ExchangeManager.Init)
store.dispatch(HomeAction.SetTermsOfUseState(preferencesStorage.wasDisclaimerAccepted()))
store.dispatch(GlobalAction.FetchUserCountry)
}
is HomeAction.ShouldScanCardOnResume -> {
@ -73,17 +75,16 @@ private fun handleHomeAction(appState: () -> AppState?, action: Action, dispatch
}
}
is HomeAction.ReadCard -> {
if (!preferencesStorage.wasDisclaimerAccepted()) {
store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer))
} else {
changeButtonState(ButtonState.PROGRESS)
val scanCardAction = GlobalAction.ScanCard(
onSuccess = ::onScanSuccess,
onFailure = ::onScanFailure,
)
store.dispatch(HomeAction.ScanInProgress(true))
postUiDelayBg(300) { store.dispatch(scanCardAction) }
}
changeButtonState(ButtonState.PROGRESS)
val scanCardAction = GlobalAction.ScanCard(
onSuccess = {
store.dispatch(HomeAction.ScanInProgress(false))
checkForDisclaimer(it, ::onScanSuccess)
},
onFailure = ::onScanFailure,
)
store.dispatch(HomeAction.ScanInProgress(true))
postUiDelayBg(300) { store.dispatch(scanCardAction) }
}
is HomeAction.GoToShop -> {
when (action.userCountryCode) {
@ -98,12 +99,28 @@ private fun handleHomeAction(appState: () -> AppState?, action: Action, dispatch
}
}
private fun checkForDisclaimer(scanResponse: ScanResponse, onDisclaimerAccepted: (ScanResponse) -> Unit) {
val disclaimerType = DisclaimerType.get(scanResponse)
store.dispatch(DisclaimerAction.SetDisclaimerType(disclaimerType))
if (disclaimerType.isAccepted()) {
onDisclaimerAccepted((scanResponse))
} else {
changeButtonState(ButtonState.ENABLED)
store.dispatch(
DisclaimerAction.Show {
changeButtonState(ButtonState.PROGRESS)
onDisclaimerAccepted(scanResponse)
},
)
}
}
private fun onScanSuccess(scanResponse: ScanResponse) {
val globalState = store.state.globalState
val tapWalletManager = globalState.tapWalletManager
tapWalletManager.updateConfigManager(scanResponse)
store.dispatch(HomeAction.ScanInProgress(false))
store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse))
if (scanResponse.isSaltPay()) {

View file

@ -4,8 +4,8 @@ import com.tangem.common.services.Result
import com.tangem.domain.common.ScanResponse
import com.tangem.domain.common.extensions.successOr
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayRegistrationStep
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayActivationStep
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.updateActivationStatus
/**
@ -21,15 +21,15 @@ class OnboardingSaltPayHelper {
return try {
val status = manager.updateActivationStatus(
amountToClaim = null,
step = SaltPayRegistrationStep.None,
step = SaltPayActivationStep.None,
).successOr { return it }
val isRegistrationCase = status.step != SaltPayRegistrationStep.Finished
val isRegistrationCase = status.step != SaltPayActivationStep.Finished
val isBackupCase = scanResponse.card.backupStatus?.isActive == false
Result.Success(isRegistrationCase || isBackupCase)
} catch (ex: Exception) {
Result.Failure(ex)
} catch (error: SaltPayRegistrationError) {
} catch (error: SaltPayActivationError) {
Result.Failure(error)
}
}

View file

@ -5,7 +5,7 @@ import com.tangem.common.CardFilter
import com.tangem.domain.common.SaltPayWorkaround
import com.tangem.tap.common.redux.StateDialog
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayState
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayRegistrationStep
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayActivationStep
import org.rekotlin.StateType
/**
@ -51,15 +51,15 @@ data class OnboardingWalletState(
}
step == OnboardingWalletStep.SaltPay && isSaltPay -> {
when (onboardingSaltPayState!!.step) {
SaltPayRegistrationStep.None, SaltPayRegistrationStep.NoGas -> 0
SaltPayRegistrationStep.NeedPin -> 7
SaltPayRegistrationStep.CardRegistration -> 8
SaltPayRegistrationStep.KycIntro, SaltPayRegistrationStep.KycStart,
SaltPayRegistrationStep.KycWaiting, SaltPayRegistrationStep.KycReject,
SaltPayActivationStep.None, SaltPayActivationStep.NoGas -> 0
SaltPayActivationStep.NeedPin -> 7
SaltPayActivationStep.CardRegistration -> 8
SaltPayActivationStep.KycIntro, SaltPayActivationStep.KycStart,
SaltPayActivationStep.KycWaiting, SaltPayActivationStep.KycReject,
-> 9
SaltPayRegistrationStep.Claim -> 10
SaltPayRegistrationStep.ClaimInProgress -> 11
SaltPayRegistrationStep.Finished -> getMaxProgress()
SaltPayActivationStep.Claim -> 10
SaltPayActivationStep.ClaimInProgress -> 11
SaltPayActivationStep.Finished -> getMaxProgress()
}
}
step == OnboardingWalletStep.Done -> getMaxProgress()

View file

@ -20,8 +20,8 @@ import com.tangem.operations.attestation.AttestWalletKeyResponse
import com.tangem.tap.common.extensions.safeUpdate
import com.tangem.tap.domain.getFirstToken
import com.tangem.tap.domain.tokens.UserWalletId
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
import com.tangem.tap.persistence.SaltPayRegistrationStorage
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
import com.tangem.tap.persistence.SaltPayActivationStorage
import java.math.BigDecimal
/**
@ -34,7 +34,7 @@ class SaltPayActivationManager(
private val kycProvider: KYCProvider,
private val paymentologyService: PaymentologyApiService,
private val gnosisRegistrator: GnosisRegistrator,
private val registrationStorage: SaltPayRegistrationStorage,
private val registrationStorage: SaltPayActivationStorage,
) {
val kycUrlProvider = KYCUrlProvider(walletPublicKey, kycProvider)
@ -52,9 +52,9 @@ class SaltPayActivationManager(
is com.tangem.blockchain.extensions.Result.Success -> if (hasGasResult.data) {
Result.Success(Unit)
} else {
Result.Failure(SaltPayRegistrationError.NoGas)
Result.Failure(SaltPayActivationError.NoGas)
}
is com.tangem.blockchain.extensions.Result.Failure -> Result.Failure(SaltPayRegistrationError.NoGas)
is com.tangem.blockchain.extensions.Result.Failure -> Result.Failure(SaltPayActivationError.NoGas)
}
}
@ -70,10 +70,10 @@ class SaltPayActivationManager(
return try {
if (!registrationResponse.success || registrationResponse.results.isEmpty()) {
throw SaltPayRegistrationError.EmptyResponse(registrationResponse.error)
throw SaltPayActivationError.EmptyResponse(registrationResponse.error)
}
Result.Success(registrationResponse.results[0])
} catch (ex: SaltPayRegistrationError) {
} catch (ex: SaltPayActivationError) {
Result.Failure(ex)
}
}
@ -114,11 +114,11 @@ class SaltPayActivationManager(
suspend fun getAmountToClaim(): Result<Amount> {
val amount = gnosisRegistrator.getAllowance().successOr {
return Result.Failure(SaltPayRegistrationError.FailedToGetFundsToClaim)
return Result.Failure(SaltPayActivationError.FailedToGetFundsToClaim)
}
return if (amount.value == null || amount.value?.isZero() == true) {
Result.Failure(SaltPayRegistrationError.NoFundsToClaim)
Result.Failure(SaltPayActivationError.NoFundsToClaim)
} else {
Result.Success(amount)
}
@ -126,7 +126,7 @@ class SaltPayActivationManager(
suspend fun claim(amountToClaim: BigDecimal, signer: TransactionSigner): Result<Unit> {
val result = gnosisRegistrator.transferFrom(amountToClaim, signer).successOr {
return Result.Failure(SaltPayRegistrationError.ClaimTransactionFailed)
return Result.Failure(SaltPayActivationError.ClaimTransactionFailed)
}
return Result.Success(Unit)
}
@ -166,7 +166,7 @@ class SaltPayActivationManager(
kycProvider = SaltPayConfig.stub().kycProvider,
paymentologyService = PaymentologyApiService.stub(),
gnosisRegistrator = GnosisRegistrator.stub(),
registrationStorage = SaltPayRegistrationStorage.stub(),
registrationStorage = SaltPayActivationStorage.stub(),
cardId = "",
cardPublicKey = byteArrayOf(),
walletPublicKey = byteArrayOf(),

View file

@ -4,7 +4,7 @@ import com.tangem.common.core.TangemSdkError
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.SaltPayDialog
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
import com.tangem.tap.store
/**
@ -14,9 +14,9 @@ class SaltPayExceptionHandler {
companion object {
fun handle(throwable: Throwable) {
when (throwable) {
is SaltPayRegistrationError -> {
is SaltPayActivationError -> {
val dialog = when (throwable) {
is SaltPayRegistrationError.NoGas -> SaltPayDialog.Activation.NoGas
is SaltPayActivationError.NoGas -> SaltPayDialog.Activation.NoGas
else -> SaltPayDialog.Activation.OnError(throwable)
}
store.dispatchDialogShow(dialog)

View file

@ -2,7 +2,7 @@ package com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog
import com.tangem.common.extensions.VoidCallback
import com.tangem.tap.common.redux.StateDialog
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
/**
[REDACTED_AUTHOR]
@ -10,7 +10,7 @@ import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPa
sealed class SaltPayDialog : StateDialog {
sealed class Activation : SaltPayDialog() {
object NoGas : SaltPayDialog()
data class OnError(val error: SaltPayRegistrationError) : SaltPayDialog()
data class OnError(val error: SaltPayActivationError) : SaltPayDialog()
data class TryToInterrupt(val onOk: VoidCallback, val onCancel: VoidCallback) : SaltPayDialog()
}
}

View file

@ -20,7 +20,7 @@ sealed class SaltPayModuleError(
}
}
sealed class SaltPayRegistrationError(
sealed class SaltPayActivationError(
subCode: Int,
message: String? = null,
override val data: Any? = null,
@ -28,27 +28,27 @@ sealed class SaltPayRegistrationError(
subCode = ERROR_CODE_REGISTRATION + subCode,
message = message ?: EMPTY_MESSAGE,
) {
object Unknown : SaltPayRegistrationError(4)
object Empty : SaltPayRegistrationError(4)
object Unknown : SaltPayActivationError(4)
object Empty : SaltPayActivationError(4)
// gnosis
object FailedToMakeTxData : SaltPayRegistrationError(1)
object FailedToSendTx : SaltPayRegistrationError(2)
object FailedToMakeTxData : SaltPayActivationError(1)
object FailedToSendTx : SaltPayActivationError(2)
object NeedPin : SaltPayRegistrationError(3)
object NoGas : SaltPayRegistrationError(5) //
class EmptyResponse(message: String?) : SaltPayRegistrationError(6, message)
class CardNotFound(message: String?) : SaltPayRegistrationError(8, message)
class CardDisabled(message: String?) : SaltPayRegistrationError(9, message)
class CardNotPassed(message: String?) : SaltPayRegistrationError(10, message)
object EmptyDynamicAttestResponse : SaltPayRegistrationError(11)
object EmptyBackupCardScanned : SaltPayRegistrationError(12)
object WeakPin : SaltPayRegistrationError(13)
object NeedPin : SaltPayActivationError(3)
object NoGas : SaltPayActivationError(5) //
class EmptyResponse(message: String?) : SaltPayActivationError(6, message)
class CardNotFound(message: String?) : SaltPayActivationError(8, message)
class CardDisabled(message: String?) : SaltPayActivationError(9, message)
class CardNotPassed(message: String?) : SaltPayActivationError(10, message)
object EmptyDynamicAttestResponse : SaltPayActivationError(11)
object EmptyBackupCardScanned : SaltPayActivationError(12)
object WeakPin : SaltPayActivationError(13)
object FailedToGetFundsToClaim : SaltPayRegistrationError(14)
object NoFundsToClaim : SaltPayRegistrationError(15)
object ClaimTransactionFailed : SaltPayRegistrationError(16)
object NotClaimed : SaltPayRegistrationError(17)
object FailedToGetFundsToClaim : SaltPayActivationError(14)
object NoFundsToClaim : SaltPayActivationError(15)
object ClaimTransactionFailed : SaltPayActivationError(16)
object NotClaimed : SaltPayActivationError(17)
companion object {
const val EMPTY_MESSAGE = ""

View file

@ -33,7 +33,7 @@ sealed class OnboardingSaltPayAction : Action {
data class TrySetPin(val pin: String) : OnboardingSaltPayAction()
data class SetPin(val pin: String) : OnboardingSaltPayAction()
data class SetStep(val newStep: SaltPayRegistrationStep? = null) : OnboardingSaltPayAction()
data class SetStep(val newStep: SaltPayActivationStep? = null) : OnboardingSaltPayAction()
data class SetAmountToClaim(val amount: Amount?) : OnboardingSaltPayAction()
data class SetTokenBalance(val balanceValue: BigDecimal) : OnboardingSaltPayAction()
}

View file

@ -19,7 +19,7 @@ import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWallet
import com.tangem.tap.features.onboarding.products.wallet.saltPay.AllSymbolsTheSameFilter
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayExceptionHandler
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayRegistrationError
import com.tangem.tap.features.onboarding.products.wallet.saltPay.message.SaltPayActivationError
import com.tangem.tap.scope
import com.tangem.tap.store
import com.tangem.tap.tangemSdk
@ -89,7 +89,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
}
val pinCode = state.pinCode.guard {
onError(SaltPayRegistrationError.NeedPin)
onError(SaltPayActivationError.NeedPin)
return@launch
}
@ -99,7 +99,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
}
if (!attestationResponse.success) {
onError(SaltPayRegistrationError.CardNotFound(attestationResponse.error))
onError(SaltPayActivationError.CardNotFound(attestationResponse.error))
return@launch
}
@ -117,7 +117,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
}
saltPayManager.sendTransactions(registrationResponse.signedTransactions).successOr {
onError(SaltPayRegistrationError.FailedToSendTx)
onError(SaltPayActivationError.FailedToSendTx)
return@launch
}
@ -128,12 +128,12 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
withMainContext {
handleInProgress = false
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.KycIntro))
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycIntro))
}
}
}
is OnboardingSaltPayAction.OpenUtorgKYC -> {
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.KycStart))
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycStart))
}
is OnboardingSaltPayAction.UtorgKYCRedirectSuccess -> {
store.dispatch(OnboardingSaltPayAction.RegisterKYC)
@ -155,8 +155,8 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
try {
assertPinValid(action.pin, getState().pinLength)
store.dispatch(OnboardingSaltPayAction.SetPin(action.pin))
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.CardRegistration))
} catch (error: SaltPayRegistrationError) {
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.CardRegistration))
} catch (error: SaltPayActivationError) {
SaltPayExceptionHandler.handle(error)
}
}
@ -166,7 +166,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
scope.launch {
val amountToClaim = getAmountToClaimIfNeeded(state.saltPayManager, state.amountToClaim).guard {
onException(SaltPayRegistrationError.NoFundsToClaim)
onException(SaltPayActivationError.NoFundsToClaim)
return@launch
}
@ -187,12 +187,12 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
)
}
state.saltPayManager.claim(amountToClaim.value!!, signer).successOr {
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.Claim))
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.Claim))
onException(it.error)
return@launch
}
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.ClaimInProgress))
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.ClaimInProgress))
dispatchOnMain(OnboardingSaltPayAction.RefreshClaim)
}
}
@ -211,7 +211,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
handleInProgress = false
handleClaimRefreshInProgress = false
dispatchOnMain(OnboardingSaltPayAction.SetTokenBalance(balance))
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.Finished))
dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.Finished))
}
}
else -> {
@ -221,13 +221,13 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
}
data class UpdateResult(
val step: SaltPayRegistrationStep = SaltPayRegistrationStep.None,
val step: SaltPayActivationStep = SaltPayActivationStep.None,
val amountToClaim: Amount? = null,
)
suspend fun SaltPayActivationManager.updateActivationStatus(
amountToClaim: Amount?,
step: SaltPayRegistrationStep,
step: SaltPayActivationStep,
): Result<UpdateResult> {
Timber.d("updateSaltPayStatus")
var updateResult = UpdateResult()
@ -248,9 +248,9 @@ suspend fun SaltPayActivationManager.updateActivationStatus(
val fetchedAmountToClaim = getAmountToClaimIfNeeded(this, amountToClaim)
updateResult = when {
// if fetchedAmountToClaim = null -> then it already claimed
saltPayStep == SaltPayRegistrationStep.Claim && fetchedAmountToClaim == null -> {
saltPayStep == SaltPayActivationStep.Claim && fetchedAmountToClaim == null -> {
updateResult.copy(
step = SaltPayRegistrationStep.Finished,
step = SaltPayActivationStep.Finished,
amountToClaim = fetchedAmountToClaim,
)
}
@ -298,7 +298,7 @@ private var handleInProgress: Boolean = false
store.dispatchOnMain(OnboardingSaltPayAction.SetInProgress(value))
}
private suspend fun onError(error: SaltPayRegistrationError) {
private suspend fun onError(error: SaltPayActivationError) {
withMainContext {
handleInProgress = false
SaltPayExceptionHandler.handle(error)
@ -314,12 +314,12 @@ private suspend fun onException(error: Throwable) {
private suspend fun checkGasIfNeeded(
saltPayManager: SaltPayActivationManager,
step: SaltPayRegistrationStep,
step: SaltPayActivationStep,
): Result<Unit> {
Timber.d("checkGasIfNeeded: for step: %s", step)
if (step == SaltPayRegistrationStep.KycStart ||
step == SaltPayRegistrationStep.KycWaiting ||
step == SaltPayRegistrationStep.Finished
if (step == SaltPayActivationStep.KycStart ||
step == SaltPayActivationStep.KycWaiting ||
step == SaltPayActivationStep.Finished
) {
Timber.d("checkGasIfNeeded: no need to check for step: %s", step)
return Result.Success(Unit)
@ -335,17 +335,17 @@ private suspend fun checkGasIfNeeded(
private suspend fun registerKYCIfNeeded(
saltPayManager: SaltPayActivationManager,
step: SaltPayRegistrationStep,
step: SaltPayActivationStep,
): Result<Unit> {
Timber.d("registerKYCIfNeeded: step: %s", step)
if (step != SaltPayRegistrationStep.KycStart) {
if (step != SaltPayActivationStep.KycStart) {
Timber.d("registerKYCIfNeeded: return Success, because step != KycStart")
return Result.Success(Unit)
}
withMainContext {
Timber.d("registerKYCIfNeeded: set new step: KycWaiting")
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayRegistrationStep.KycWaiting))
store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycWaiting))
}
Timber.d("saltPayManager.registerKYC()")
@ -354,7 +354,7 @@ private suspend fun registerKYCIfNeeded(
private suspend fun checkRegistration(
saltPayManager: SaltPayActivationManager,
): Result<SaltPayRegistrationStep> {
): Result<SaltPayActivationStep> {
Timber.d("checkRegistration")
return try {
val registrationResponseItem = saltPayManager.checkRegistration().successOr {
@ -366,51 +366,51 @@ private suspend fun checkRegistration(
val step = registrationResponseItem.toSaltPayStep()
Timber.d("checkRegistration: step: %s", step)
Result.Success(step)
} catch (ex: SaltPayRegistrationError) {
} catch (ex: SaltPayActivationError) {
Timber.e(ex, "checkRegistration: step")
Result.Failure(ex)
}
}
@Throws(SaltPayRegistrationError::class)
fun RegistrationResponse.Item.toSaltPayStep(): SaltPayRegistrationStep {
@Throws(SaltPayActivationError::class)
fun RegistrationResponse.Item.toSaltPayStep(): SaltPayActivationStep {
return when {
passed != true -> throw SaltPayRegistrationError.CardNotPassed(this.error)
disabledByAdmin == true -> throw SaltPayRegistrationError.CardDisabled(this.error)
passed != true -> throw SaltPayActivationError.CardNotPassed(this.error)
disabledByAdmin == true -> throw SaltPayActivationError.CardDisabled(this.error)
// go to claim screen
active == true -> SaltPayRegistrationStep.Claim
active == true -> SaltPayActivationStep.Claim
// pinSet is false, go toPin screen
pinSet == false -> SaltPayRegistrationStep.NeedPin
pinSet == false -> SaltPayActivationStep.NeedPin
kycStatus != null -> {
when (kycStatus) {
KYCStatus.NOT_STARTED, KYCStatus.STARTED -> SaltPayRegistrationStep.KycStart
KYCStatus.WAITING_FOR_APPROVAL -> SaltPayRegistrationStep.KycWaiting
KYCStatus.CORRECTION_REQUESTED, KYCStatus.REJECTED -> SaltPayRegistrationStep.KycReject
KYCStatus.APPROVED -> SaltPayRegistrationStep.Claim
KYCStatus.NOT_STARTED, KYCStatus.STARTED -> SaltPayActivationStep.KycStart
KYCStatus.WAITING_FOR_APPROVAL -> SaltPayActivationStep.KycWaiting
KYCStatus.CORRECTION_REQUESTED, KYCStatus.REJECTED -> SaltPayActivationStep.KycReject
KYCStatus.APPROVED -> SaltPayActivationStep.Claim
null -> throw UnsupportedOperationException()
}
}
// kycDate is set, go to kyc waiting screen
kycDate != null -> SaltPayRegistrationStep.KycWaiting
kycDate != null -> SaltPayActivationStep.KycWaiting
else -> SaltPayRegistrationStep.KycIntro
else -> SaltPayActivationStep.KycIntro
}
}
@Throws(SaltPayRegistrationError::class)
@Throws(SaltPayActivationError::class)
private fun assertPinValid(pin: String, pinLength: Int) {
val array = pin.toCharArray()
if (array.size < pinLength) throw SaltPayRegistrationError.WeakPin
if (array.size < pinLength) throw SaltPayActivationError.WeakPin
val filters: List<Filter<String>> = listOf(
AllSymbolsTheSameFilter(),
)
if (filters.any { it.filter(pin) }) {
throw SaltPayRegistrationError.WeakPin
throw SaltPayActivationError.WeakPin
}
}

View file

@ -17,7 +17,7 @@ import com.tangem.tap.features.onboarding.products.wallet.saltPay.KYCProvider
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayConfig
import com.tangem.tap.features.wallet.redux.ProgressState
import com.tangem.tap.persistence.SaltPayRegistrationStorage
import com.tangem.tap.persistence.SaltPayActivationStorage
import com.tangem.tap.preferencesStorage
import com.tangem.tap.store
import java.math.BigDecimal
@ -33,7 +33,7 @@ data class OnboardingSaltPayState(
val accessCode: String? = null,
val amountToClaim: Amount? = null,
val tokenAmount: Amount = Amount(SaltPayWorkaround.tokenFrom(Blockchain.SaltPay), BigDecimal.ZERO),
val step: SaltPayRegistrationStep = SaltPayRegistrationStep.None,
val step: SaltPayActivationStep = SaltPayActivationStep.None,
val saltPayCardArtworkUrl: String? = null,
val inProgress: Boolean = false,
val claimInProgress: Boolean = false,
@ -60,7 +60,7 @@ data class OnboardingSaltPayState(
scanResponse = scanResponse,
gnosisRegistrator = gnosisRegistrator,
paymentologyService = store.state.domainNetworks.paymentologyService,
registrationStorage = preferencesStorage.saltPayRegistrationStorage,
registrationStorage = preferencesStorage.saltPayActivationStorage,
kycProvider = saltPayConfig.kycProvider,
)
test(scanResponse, gnosisRegistrator)
@ -83,7 +83,7 @@ data class OnboardingSaltPayState(
scanResponse: ScanResponse,
gnosisRegistrator: GnosisRegistrator,
paymentologyService: PaymentologyApiService,
registrationStorage: SaltPayRegistrationStorage,
registrationStorage: SaltPayActivationStorage,
kycProvider: KYCProvider,
): SaltPayActivationManager {
if (!scanResponse.isSaltPay()) {
@ -115,7 +115,7 @@ data class OnboardingSaltPayState(
}
}
enum class SaltPayRegistrationStep {
enum class SaltPayActivationStep {
None,
NoGas,
NeedPin,

View file

@ -41,7 +41,7 @@ import com.tangem.tap.features.onboarding.products.wallet.saltPay.UtorgWebViewCl
import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.SaltPayDialog
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayState
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayRegistrationStep
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.SaltPayActivationStep
import com.tangem.tap.features.onboarding.products.wallet.ui.OnboardingWalletFragment
import com.tangem.tap.features.wallet.redux.ProgressState
import com.tangem.tap.store
@ -67,7 +67,7 @@ internal class OnboardingSaltPayView(
}
private var progressButton: SaltPayProgressButton? = null
private var previousStep: SaltPayRegistrationStep = SaltPayRegistrationStep.None
private var previousStep: SaltPayActivationStep = SaltPayActivationStep.None
fun newState(state: OnboardingWalletState) {
handleCardArtworks(state)
@ -133,16 +133,16 @@ internal class OnboardingSaltPayView(
walletFragment.bindingSaltPay.onboardingSaltpayContainer.show()
when (state.step) {
SaltPayRegistrationStep.NoGas -> handleNoGas()
SaltPayRegistrationStep.NeedPin -> handleNeedPin()
SaltPayRegistrationStep.CardRegistration -> handleCardRegistration()
SaltPayRegistrationStep.KycIntro -> handleKycIntro()
SaltPayRegistrationStep.KycStart -> handleKycStart(state)
SaltPayRegistrationStep.KycWaiting -> handleKycWaiting()
SaltPayRegistrationStep.KycReject -> handleKycReject()
SaltPayRegistrationStep.Claim -> handleClaim(state)
SaltPayRegistrationStep.ClaimInProgress -> handleClaim(state)
SaltPayRegistrationStep.Finished -> handleClaim(state)
SaltPayActivationStep.NoGas -> handleNoGas()
SaltPayActivationStep.NeedPin -> handleNeedPin()
SaltPayActivationStep.CardRegistration -> handleCardRegistration()
SaltPayActivationStep.KycIntro -> handleKycIntro()
SaltPayActivationStep.KycStart -> handleKycStart(state)
SaltPayActivationStep.KycWaiting -> handleKycWaiting()
SaltPayActivationStep.KycReject -> handleKycReject()
SaltPayActivationStep.Claim -> handleClaim(state)
SaltPayActivationStep.ClaimInProgress -> handleClaim(state)
SaltPayActivationStep.Finished -> handleClaim(state)
}
progressButton?.changeState(state.mainButtonState)
}
@ -276,7 +276,7 @@ internal class OnboardingSaltPayView(
topContainer.onboardingTvBalance.tvBalanceCurrency.text = ""
when (state.step) {
SaltPayRegistrationStep.Claim -> {
SaltPayActivationStep.Claim -> {
btnRefreshBalanceWidget.mainView.hide()
claimValueString(state)?.let {
tvHeader.text = getString(R.string.onboarding_title_claim, it)
@ -288,13 +288,13 @@ internal class OnboardingSaltPayView(
store.dispatch(OnboardingSaltPayAction.Claim)
}
}
SaltPayRegistrationStep.ClaimInProgress -> {
SaltPayActivationStep.ClaimInProgress -> {
btnRefreshBalanceWidget.mainView.show()
tvHeader.text = getString(R.string.onboarding_title_claim_progress)
tvBody.text = getString(R.string.onboarding_subtitle_claim_progress)
btnMain.text = getString(R.string.onboarding_button_claim)
}
SaltPayRegistrationStep.Finished -> {
SaltPayActivationStep.Finished -> {
tvHeader.setText(R.string.common_success)
tvBody.setText(R.string.onboarding_subtitle_success_claim)
@ -329,7 +329,7 @@ internal class OnboardingSaltPayView(
)
}
private fun updateConstraints(currentStep: SaltPayRegistrationStep, @LayoutRes layoutId: Int) {
private fun updateConstraints(currentStep: SaltPayActivationStep, @LayoutRes layoutId: Int) {
if (this.previousStep == currentStep) return
with(claimBinding.onboardingTopContainer) {

View file

@ -0,0 +1,25 @@
package com.tangem.tap.persistence
import android.content.SharedPreferences
import androidx.core.content.edit
/**
[REDACTED_AUTHOR]
*/
class DisclaimerPrefStorage(
private val preferences: SharedPreferences,
) {
var hasTangemTosAccepted: Boolean
get() = preferences.getBoolean(KEY_TANGEM_TOS, false)
set(value) = preferences.edit { putBoolean(KEY_TANGEM_TOS, value) }
var hasSaltPayTosAccepted: Boolean
get() = preferences.getBoolean(KEY_SALT_PAY_TOS, false)
set(value) = preferences.edit { putBoolean(KEY_SALT_PAY_TOS, value) }
companion object {
private const val KEY_TANGEM_TOS = "tangem_tos_accepted"
private const val KEY_SALT_PAY_TOS = "saltPay_tos_accepted"
}
}

View file

@ -7,15 +7,16 @@ import androidx.core.content.edit
import com.tangem.common.json.MoshiJsonConverter
import java.util.*
class PreferencesStorage(applicationContext: Application) {
private val preferences: SharedPreferences = applicationContext.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)
private val preferences: SharedPreferences =
applicationContext.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)
val appRatingLaunchObserver: AppRatingLaunchObserver
val usedCardsPrefStorage: UsedCardsPrefStorage
val fiatCurrenciesPrefStorage: FiatCurrenciesPrefStorage
val saltPayRegistrationStorage: SaltPayRegistrationStorage
val saltPayActivationStorage: SaltPayActivationStorage
val disclaimerPrefStorage: DisclaimerPrefStorage
init {
incrementLaunchCounter()
@ -24,7 +25,8 @@ class PreferencesStorage(applicationContext: Application) {
usedCardsPrefStorage.migrate()
fiatCurrenciesPrefStorage = FiatCurrenciesPrefStorage(preferences, MoshiJsonConverter.INSTANCE)
fiatCurrenciesPrefStorage.migrate()
saltPayRegistrationStorage = SaltPayRegistrationPrefStorage(applicationContext, MoshiJsonConverter.INSTANCE)
saltPayActivationStorage = SaltPayActivationPrefStorage(applicationContext, MoshiJsonConverter.INSTANCE)
disclaimerPrefStorage = DisclaimerPrefStorage(preferences)
}
var chatFirstLaunchTime: Long?
@ -38,14 +40,6 @@ class PreferencesStorage(applicationContext: Application) {
return usedCardsPrefStorage.wasScanned(cardId)
}
fun saveDisclaimerAccepted() {
preferences.edit { putBoolean(DISCLAIMER_ACCEPTED_KEY, true) }
}
fun wasDisclaimerAccepted(): Boolean {
return preferences.getBoolean(DISCLAIMER_ACCEPTED_KEY, false)
}
fun saveTwinsOnboardingShown() {
preferences.edit { putBoolean(TWINS_ONBOARDING_SHOWN_KEY, true) }
}
@ -61,12 +55,10 @@ class PreferencesStorage(applicationContext: Application) {
companion object {
private const val PREFERENCES_NAME = "tapPrefs"
private const val DISCLAIMER_ACCEPTED_KEY = "disclaimerAccepted"
private const val TWINS_ONBOARDING_SHOWN_KEY = "twinsOnboardingShown"
private const val APP_LAUNCH_COUNT_KEY = "launchCount"
private const val CHAT_FIRST_LAUNCH_KEY = "chatFirstLaunchKey"
}
}
class AppRatingLaunchObserver(

View file

@ -10,27 +10,27 @@ import com.tangem.tangem_sdk_new.storage.createEncryptedSharedPreferences
/**
[REDACTED_AUTHOR]
*/
interface SaltPayRegistrationStorage {
var data: SaltPayRegistratorData
interface SaltPayActivationStorage {
var data: SaltPayActivationData
fun reset()
companion object {
fun stub(): SaltPayRegistrationStorage = object : SaltPayRegistrationStorage {
override var data: SaltPayRegistratorData = SaltPayRegistratorData()
fun stub(): SaltPayActivationStorage = object : SaltPayActivationStorage {
override var data: SaltPayActivationData = SaltPayActivationData()
override fun reset() {}
}
}
}
data class SaltPayRegistratorData(
data class SaltPayActivationData(
val transactionsSent: Boolean = false,
)
class SaltPayRegistrationPrefStorage(
class SaltPayActivationPrefStorage(
context: Context,
private val converter: MoshiJsonConverter,
) : SaltPayRegistrationStorage {
) : SaltPayActivationStorage {
private val storage: ArmadilloSharedPreferences = SecureStorage.createEncryptedSharedPreferences(
context = context,
@ -43,7 +43,7 @@ class SaltPayRegistrationPrefStorage(
fetch()
}
override var data: SaltPayRegistratorData = SaltPayRegistratorData()
override var data: SaltPayActivationData = SaltPayActivationData()
set(value) {
field = value
if (!isFetching) save()
@ -52,7 +52,7 @@ class SaltPayRegistrationPrefStorage(
override fun reset() {
storage.edit(true) {
this.remove(REGISTRATION_DATA_KEY)
data = SaltPayRegistratorData()
data = SaltPayActivationData()
}
}
@ -62,14 +62,14 @@ class SaltPayRegistrationPrefStorage(
}
}
private fun fetch(): SaltPayRegistratorData {
private fun fetch(): SaltPayActivationData {
isFetching = true
val jsonData = storage.getString(REGISTRATION_DATA_KEY, null)
data = if (jsonData == null) {
SaltPayRegistratorData()
SaltPayActivationData()
} else {
converter.fromJson<SaltPayRegistratorData>(jsonData) ?: SaltPayRegistratorData()
converter.fromJson<SaltPayActivationData>(jsonData) ?: SaltPayActivationData()
}
isFetching = false

View file

@ -22,6 +22,7 @@
android:layout_height="?attr/actionBarSize"
app:navigationIcon="@drawable/ic_baseline_arrow_back_24"
app:title="@string/disclaimer_title" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.constraintlayout.widget.ConstraintLayout
@ -31,17 +32,26 @@
android:background="@color/white"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<WebView
android:id="@+id/web_view"
android:layout_width="0dp"
android:layout_height="0dp"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="24dp"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingTop="16dp"
android:paddingBottom="120dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent">
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.core.widget.NestedScrollView>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"