Updated on 2026-08-14
This commit is contained in:
parent
64af848bd9
commit
cc468b2d0d
17 changed files with 579 additions and 94 deletions
1
.idea/dictionaries/romanpotapov.xml
generated
1
.idea/dictionaries/romanpotapov.xml
generated
|
|
@ -2,6 +2,7 @@
|
||||||
<dictionary name="romanpotapov">
|
<dictionary name="romanpotapov">
|
||||||
<words>
|
<words>
|
||||||
<w>blockchain</w>
|
<w>blockchain</w>
|
||||||
|
<w>passcode</w>
|
||||||
<w>tangem</w>
|
<w>tangem</w>
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
package com.tangem.tap.common.entities
|
package com.tangem.tap.common.entities
|
||||||
|
|
||||||
abstract class Button(val enabled: Boolean)
|
open class Button(val enabled: Boolean)
|
||||||
|
|
@ -6,6 +6,7 @@ import androidx.fragment.app.FragmentManager
|
||||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||||
import com.tangem.tap.features.details.ui.DetailsConfirmFragment
|
import com.tangem.tap.features.details.ui.DetailsConfirmFragment
|
||||||
import com.tangem.tap.features.details.ui.DetailsFragment
|
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.home.HomeFragment
|
||||||
import com.tangem.tap.features.send.ui.SendFragment
|
import com.tangem.tap.features.send.ui.SendFragment
|
||||||
import com.tangem.tap.features.wallet.ui.WalletFragment
|
import com.tangem.tap.features.wallet.ui.WalletFragment
|
||||||
|
|
@ -40,5 +41,6 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
|
||||||
AppScreen.Send -> SendFragment()
|
AppScreen.Send -> SendFragment()
|
||||||
AppScreen.Details -> DetailsFragment()
|
AppScreen.Details -> DetailsFragment()
|
||||||
AppScreen.DetailsConfirm -> DetailsConfirmFragment()
|
AppScreen.DetailsConfirm -> DetailsConfirmFragment()
|
||||||
|
AppScreen.DetailsSecurity -> DetailsSecurityFragment()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,4 +9,4 @@ data class NavigationState(
|
||||||
val activity: WeakReference<FragmentActivity>? = null
|
val activity: WeakReference<FragmentActivity>? = null
|
||||||
) : StateType
|
) : StateType
|
||||||
|
|
||||||
enum class AppScreen { Home, Wallet, Send, Details, DetailsConfirm }
|
enum class AppScreen { Home, Wallet, Send, Details, DetailsConfirm, DetailsSecurity }
|
||||||
|
|
@ -2,11 +2,10 @@ package com.tangem.tap.domain
|
||||||
|
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import com.tangem.*
|
import com.tangem.*
|
||||||
import com.tangem.commands.CommandResponse
|
import com.tangem.commands.*
|
||||||
import com.tangem.commands.PurgeWalletCommand
|
|
||||||
import com.tangem.commands.PurgeWalletResponse
|
|
||||||
import com.tangem.common.CompletionResult
|
import com.tangem.common.CompletionResult
|
||||||
import com.tangem.common.extensions.CardType
|
import com.tangem.common.extensions.CardType
|
||||||
|
import com.tangem.common.extensions.calculateSha256
|
||||||
import com.tangem.tangem_sdk_new.extensions.init
|
import com.tangem.tangem_sdk_new.extensions.init
|
||||||
import com.tangem.tap.domain.tasks.CreateWalletAndRescanTask
|
import com.tangem.tap.domain.tasks.CreateWalletAndRescanTask
|
||||||
import com.tangem.tap.domain.tasks.ScanNoteResponse
|
import com.tangem.tap.domain.tasks.ScanNoteResponse
|
||||||
|
|
@ -26,12 +25,28 @@ class TangemSdkManager(val activity: ComponentActivity) {
|
||||||
return runTaskAsyncReturnOnMain(ScanNoteTask())
|
return runTaskAsyncReturnOnMain(ScanNoteTask())
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun createWallet(): CompletionResult<ScanNoteResponse> {
|
suspend fun createWallet(cardId: String?): CompletionResult<ScanNoteResponse> {
|
||||||
return runTaskAsyncReturnOnMain(CreateWalletAndRescanTask())
|
return runTaskAsyncReturnOnMain(CreateWalletAndRescanTask(), cardId)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun eraseWallet(): CompletionResult<PurgeWalletResponse> {
|
suspend fun eraseWallet(cardId: String?): CompletionResult<PurgeWalletResponse> {
|
||||||
return runTaskAsyncReturnOnMain(PurgeWalletCommand())
|
return runTaskAsyncReturnOnMain(PurgeWalletCommand(), cardId)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun setPasscode(cardId: String?): CompletionResult<SetPinResponse> {
|
||||||
|
return runTaskAsyncReturnOnMain(SetPinCommand.setPin1(null), cardId)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun setAccessCode(cardId: String?): CompletionResult<SetPinResponse> {
|
||||||
|
return runTaskAsyncReturnOnMain(SetPinCommand.setPin2(null), cardId)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun setLongTap(cardId: String?): CompletionResult<SetPinResponse> {
|
||||||
|
return runTaskAsyncReturnOnMain(SetPinCommand(
|
||||||
|
pinType = PinType.Pin1,
|
||||||
|
newPin1 = tangemSdk.config.defaultPin1.calculateSha256(),
|
||||||
|
newPin2 = tangemSdk.config.defaultPin2.calculateSha256()
|
||||||
|
), cardId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun <T : CommandResponse> runTaskAsync(
|
private suspend fun <T : CommandResponse> runTaskAsync(
|
||||||
|
|
|
||||||
|
|
@ -41,4 +41,18 @@ sealed class DetailsAction : Action {
|
||||||
data class SelectAppCurrency(val fiatCurrencyName: FiatCurrencyName): AppCurrencyAction()
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -18,11 +18,24 @@ import kotlinx.coroutines.withContext
|
||||||
import org.rekotlin.Middleware
|
import org.rekotlin.Middleware
|
||||||
|
|
||||||
class DetailsMiddleware {
|
class DetailsMiddleware {
|
||||||
|
private val eraseWalletMiddleware = EraseWalletMiddleware()
|
||||||
|
private val appCurrencyMiddleware = AppCurrencyMiddleware()
|
||||||
|
private val manageSecurityMiddleware = ManageSecurityMiddleware()
|
||||||
val detailsMiddleware: Middleware<AppState> = { dispatch, state ->
|
val detailsMiddleware: Middleware<AppState> = { dispatch, state ->
|
||||||
{ next ->
|
{ next ->
|
||||||
{ action ->
|
{ action ->
|
||||||
when (action) {
|
when (action) {
|
||||||
is DetailsAction.PrepareScreen -> {
|
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 {
|
scope.launch {
|
||||||
val loadedCurrencies = preferencesStorage.getFiatCurrencies()
|
val loadedCurrencies = preferencesStorage.getFiatCurrencies()
|
||||||
if (loadedCurrencies.isNullOrEmpty()) {
|
if (loadedCurrencies.isNullOrEmpty()) {
|
||||||
|
|
@ -41,8 +54,11 @@ class DetailsMiddleware {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class EraseWalletMiddleware() {
|
||||||
|
fun handle(action: DetailsAction.EraseWallet) {
|
||||||
|
when (action) {
|
||||||
is DetailsAction.EraseWallet.Proceed -> {
|
is DetailsAction.EraseWallet.Proceed -> {
|
||||||
when (store.state.detailsState.eraseWalletState) {
|
when (store.state.detailsState.eraseWalletState) {
|
||||||
EraseWalletState.Allowed ->
|
EraseWalletState.Allowed ->
|
||||||
|
|
@ -58,7 +74,9 @@ class DetailsMiddleware {
|
||||||
}
|
}
|
||||||
is DetailsAction.EraseWallet.Confirm -> {
|
is DetailsAction.EraseWallet.Confirm -> {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val result = tangemSdkManager.eraseWallet()
|
val result = tangemSdkManager.eraseWallet(
|
||||||
|
store.state.detailsState.card?.cardId
|
||||||
|
)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
when (result) {
|
when (result) {
|
||||||
is CompletionResult.Success -> {
|
is CompletionResult.Success -> {
|
||||||
|
|
@ -68,13 +86,58 @@ class DetailsMiddleware {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppCurrencyMiddleware {
|
||||||
|
fun handle(action: DetailsAction.AppCurrencyAction) {
|
||||||
|
when (action) {
|
||||||
is DetailsAction.AppCurrencyAction.SelectAppCurrency -> {
|
is DetailsAction.AppCurrencyAction.SelectAppCurrency -> {
|
||||||
preferencesStorage.saveAppCurrency(action.fiatCurrencyName)
|
preferencesStorage.saveAppCurrency(action.fiatCurrencyName)
|
||||||
store.dispatch(GlobalAction.ChangeAppCurrency(action.fiatCurrencyName))
|
store.dispatch(GlobalAction.ChangeAppCurrency(action.fiatCurrencyName))
|
||||||
store.dispatch(WalletAction.LoadFiatRate)
|
store.dispatch(WalletAction.LoadFiatRate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next(action)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.tangem.commands.Settings
|
||||||
import com.tangem.common.extensions.isZero
|
import com.tangem.common.extensions.isZero
|
||||||
import com.tangem.tap.common.redux.AppState
|
import com.tangem.tap.common.redux.AppState
|
||||||
import org.rekotlin.Action
|
import org.rekotlin.Action
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class DetailsReducer {
|
class DetailsReducer {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
@ -13,28 +14,45 @@ class DetailsReducer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun internalReduce(action: Action, state: AppState): DetailsState {
|
private fun internalReduce(action: Action, state: AppState): DetailsState {
|
||||||
|
|
||||||
if (action !is DetailsAction) return state.detailsState
|
if (action !is DetailsAction) return state.detailsState
|
||||||
|
|
||||||
var detailsState = state.detailsState
|
val detailsState = state.detailsState
|
||||||
when (action) {
|
return when (action) {
|
||||||
is DetailsAction.PrepareScreen -> {
|
is DetailsAction.PrepareScreen -> {
|
||||||
detailsState = DetailsState(
|
handlePrepareScreen(action, detailsState)
|
||||||
|
}
|
||||||
|
is DetailsAction.EraseWallet -> {
|
||||||
|
handleEraseWallet(action, detailsState)
|
||||||
|
}
|
||||||
|
is DetailsAction.AppCurrencyAction -> {
|
||||||
|
handleAppCurrencyAction(action, detailsState)
|
||||||
|
}
|
||||||
|
is DetailsAction.ManageSecurity -> {
|
||||||
|
handleSecurityAction(action, 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,
|
card = action.card, wallet = action.wallet,
|
||||||
cardInfo = action.card.toCardInfo(),
|
cardInfo = action.card.toCardInfo(),
|
||||||
appCurrencyState = AppCurrencyState(
|
appCurrencyState = AppCurrencyState(
|
||||||
action.fiatCurrencyName
|
action.fiatCurrencyName
|
||||||
|
),
|
||||||
|
securityScreenState = SecurityScreenState(currentOption = securityOption)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
is DetailsAction.EraseWallet -> {
|
|
||||||
detailsState = handleEraseWallet(action, detailsState)
|
|
||||||
}
|
|
||||||
is DetailsAction.AppCurrencyAction -> {
|
|
||||||
detailsState = handleAppCurrencyAction(action, detailsState)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return detailsState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleEraseWallet(action: DetailsAction.EraseWallet, state: DetailsState): DetailsState {
|
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? {
|
private fun Card.toCardInfo(): CardInfo? {
|
||||||
val cardId = this.cardId.chunked(4).joinToString(separator = " ")
|
val cardId = this.cardId.chunked(4).joinToString(separator = " ")
|
||||||
val issuer = this.cardData?.issuerName ?: return null
|
val issuer = this.cardData?.issuerName ?: return null
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@ package com.tangem.tap.features.details.redux
|
||||||
|
|
||||||
import com.tangem.blockchain.common.Wallet
|
import com.tangem.blockchain.common.Wallet
|
||||||
import com.tangem.commands.Card
|
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.entities.TapCurrency.Companion.DEFAULT_FIAT_CURRENCY
|
||||||
import com.tangem.tap.common.redux.global.FiatCurrencyName
|
import com.tangem.tap.common.redux.global.FiatCurrencyName
|
||||||
import com.tangem.tap.network.coinmarketcap.FiatCurrency
|
import com.tangem.tap.network.coinmarketcap.FiatCurrency
|
||||||
import org.rekotlin.StateType
|
import org.rekotlin.StateType
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
data class DetailsState(
|
data class DetailsState(
|
||||||
val card: Card? = null,
|
val card: Card? = null,
|
||||||
|
|
@ -14,6 +16,7 @@ data class DetailsState(
|
||||||
val appCurrencyState: AppCurrencyState = AppCurrencyState(),
|
val appCurrencyState: AppCurrencyState = AppCurrencyState(),
|
||||||
val eraseWalletState: EraseWalletState? = null,
|
val eraseWalletState: EraseWalletState? = null,
|
||||||
val confirmScreenState: ConfirmScreenState? = null,
|
val confirmScreenState: ConfirmScreenState? = null,
|
||||||
|
val securityScreenState: SecurityScreenState? = null,
|
||||||
) : StateType
|
) : StateType
|
||||||
|
|
||||||
data class CardInfo(
|
data class CardInfo(
|
||||||
|
|
@ -24,6 +27,14 @@ data class CardInfo(
|
||||||
|
|
||||||
enum class EraseWalletState { Allowed, NotAllowedByCard, NotEmpty }
|
enum class EraseWalletState { Allowed, NotAllowedByCard, NotEmpty }
|
||||||
enum class ConfirmScreenState { EraseWallet, LongTap, AccessCode, PassCode }
|
enum class ConfirmScreenState { EraseWallet, LongTap, AccessCode, PassCode }
|
||||||
|
data class SecurityScreenState(
|
||||||
|
val currentOption: SecurityOption = SecurityOption.LongTap,
|
||||||
|
val selectedOption: SecurityOption = currentOption,
|
||||||
|
val allowedOptions: EnumSet<SecurityOption> = EnumSet.allOf(SecurityOption::class.java),
|
||||||
|
val buttonProceed: Button = Button(true)
|
||||||
|
)
|
||||||
|
|
||||||
|
enum class SecurityOption { LongTap, PassCode, AccessCode }
|
||||||
data class AppCurrencyState(
|
data class AppCurrencyState(
|
||||||
val fiatCurrencyName: FiatCurrencyName = DEFAULT_FIAT_CURRENCY,
|
val fiatCurrencyName: FiatCurrencyName = DEFAULT_FIAT_CURRENCY,
|
||||||
val showAppCurrencyDialog: Boolean = false,
|
val showAppCurrencyDialog: Boolean = false,
|
||||||
|
|
|
||||||
|
|
@ -59,16 +59,23 @@ class DetailsConfirmFragment : Fragment(R.layout.fragment_details_confirm),
|
||||||
when (state.confirmScreenState) {
|
when (state.confirmScreenState) {
|
||||||
ConfirmScreenState.EraseWallet -> {
|
ConfirmScreenState.EraseWallet -> {
|
||||||
toolbar.title = getString(R.string.details_erase_wallet)
|
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.text = getString(R.string.details_erase_wallet)
|
||||||
btn_confirm.setCompoundDrawablesRelativeWithIntrinsicBounds(
|
btn_confirm.setCompoundDrawablesRelativeWithIntrinsicBounds(
|
||||||
null, null, getDrawable(R.drawable.ic_send), null
|
null, null, getDrawable(R.drawable.ic_send), null
|
||||||
)
|
)
|
||||||
btn_confirm.setOnClickListener { store.dispatch(DetailsAction.EraseWallet.Confirm) }
|
btn_confirm.setOnClickListener { store.dispatch(DetailsAction.EraseWallet.Confirm) }
|
||||||
}
|
}
|
||||||
ConfirmScreenState.LongTap -> TODO()
|
ConfirmScreenState.LongTap, ConfirmScreenState.AccessCode,
|
||||||
ConfirmScreenState.AccessCode -> TODO()
|
ConfirmScreenState.PassCode -> {
|
||||||
ConfirmScreenState.PassCode -> TODO()
|
toolbar.title = getString(R.string.details_manage_security)
|
||||||
null -> TODO()
|
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) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import androidx.transition.TransitionInflater
|
||||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||||
import com.tangem.tap.features.details.redux.DetailsAction
|
import com.tangem.tap.features.details.redux.DetailsAction
|
||||||
import com.tangem.tap.features.details.redux.DetailsState
|
import com.tangem.tap.features.details.redux.DetailsState
|
||||||
|
import com.tangem.tap.features.details.redux.SecurityOption
|
||||||
import com.tangem.tap.store
|
import com.tangem.tap.store
|
||||||
import com.tangem.wallet.R
|
import com.tangem.wallet.R
|
||||||
import kotlinx.android.synthetic.main.fragment_details.*
|
import kotlinx.android.synthetic.main.fragment_details.*
|
||||||
|
|
@ -74,6 +75,18 @@ class DetailsFragment : Fragment(R.layout.fragment_details), StoreSubscriber<Det
|
||||||
store.dispatch(DetailsAction.AppCurrencyAction.ChooseAppCurrency)
|
store.dispatch(DetailsAction.AppCurrencyAction.ChooseAppCurrency)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tv_security_title.setOnClickListener {
|
||||||
|
store.dispatch(DetailsAction.ManageSecurity.OpenSecurity)
|
||||||
|
}
|
||||||
|
|
||||||
|
val currentSecurity = when (state.securityScreenState?.currentOption) {
|
||||||
|
SecurityOption.LongTap -> 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 &&
|
if (state.appCurrencyState.showAppCurrencyDialog &&
|
||||||
!state.appCurrencyState.fiatCurrencies.isNullOrEmpty()) {
|
!state.appCurrencyState.fiatCurrencies.isNullOrEmpty()) {
|
||||||
currencySelectionDialog.show(
|
currencySelectionDialog.show(
|
||||||
|
|
|
||||||
|
|
@ -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<DetailsState> {
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -63,7 +63,9 @@ val walletMiddleware: Middleware<AppState> = { dispatch, state ->
|
||||||
}
|
}
|
||||||
is WalletAction.CreateWallet -> {
|
is WalletAction.CreateWallet -> {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val result = tangemSdkManager.createWallet()
|
val result = tangemSdkManager.createWallet(
|
||||||
|
store.state.globalState.scanNoteResponse?.card?.cardId
|
||||||
|
)
|
||||||
when (result) {
|
when (result) {
|
||||||
is CompletionResult.Success -> {
|
is CompletionResult.Success -> {
|
||||||
store.state.globalState.tapWalletManager.onCardScanned(result.data)
|
store.state.globalState.tapWalletManager.onCardScanned(result.data)
|
||||||
|
|
|
||||||
9
app/src/main/res/drawable/ic_save.xml
Normal file
9
app/src/main/res/drawable/ic_save.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M20.7825,6.9675L17.0325,3.2175C16.9624,3.148 16.8793,3.093 16.7879,3.0557C16.6966,3.0184 16.5987,2.9994 16.5,3H4.5C4.1022,3 3.7206,3.1581 3.4393,3.4393C3.158,3.7207 3,4.1022 3,4.5V19.5C3,19.8978 3.158,20.2794 3.4393,20.5607C3.7206,20.842 4.1022,21 4.5,21H19.5C19.8978,21 20.2794,20.842 20.5607,20.5607C20.842,20.2794 21,19.8978 21,19.5V7.5C21.0006,7.4013 20.9817,7.3035 20.9443,7.2121C20.907,7.1207 20.852,7.0376 20.7825,6.9675ZM9,4.5H15V7.5H9V4.5ZM15,19.5H9V13.5H15V19.5ZM16.5,19.5V13.5C16.5,13.1022 16.342,12.7207 16.0607,12.4394C15.7794,12.158 15.3978,12 15,12H9C8.6022,12 8.2206,12.158 7.9393,12.4394C7.658,12.7207 7.5,13.1022 7.5,13.5V19.5H4.5V4.5H7.5V7.5C7.5,7.8978 7.658,8.2794 7.9393,8.5607C8.2206,8.842 8.6022,9 9,9H15C15.3978,9 15.7794,8.842 16.0607,8.5607C16.342,8.2794 16.5,7.8978 16.5,7.5V4.8075L19.5,7.8075V19.5H16.5Z"
|
||||||
|
android:fillColor="#ffffff"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -68,34 +68,27 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
<Space
|
<androidx.constraintlayout.widget.Guideline
|
||||||
android:id="@+id/space"
|
android:id="@+id/guideline"
|
||||||
android:layout_width="93dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="48dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="30dp"
|
android:orientation="vertical"
|
||||||
android:layout_marginTop="30dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/btn_confirm"
|
app:layout_constraintGuide_percent="0.37" />
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
|
||||||
app:layout_constraintHorizontal_chainStyle="packed"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintVertical_bias="1" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn_confirm"
|
android:id="@+id/btn_confirm"
|
||||||
style="@style/TapBlackButton"
|
style="@style/TapBlackButton"
|
||||||
android:layout_width="200dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginStart="7dp"
|
android:layout_marginStart="7dp"
|
||||||
android:layout_marginTop="30dp"
|
android:layout_marginTop="30dp"
|
||||||
android:layout_marginEnd="30dp"
|
android:layout_marginEnd="30dp"
|
||||||
tools:text="@string/wallet_button_send"
|
tools:text="@string/wallet_button_send"
|
||||||
tools:icon="@drawable/ic_send"
|
tools:icon="@drawable/ic_send"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
app:layout_constraintStart_toEndOf="@+id/space"
|
|
||||||
app:layout_constraintVertical_bias="1" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
|
||||||
197
app/src/main/res/layout/fragment_details_security.xml
Normal file
197
app/src/main/res/layout/fragment_details_security.xml
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/coordinator_details_confirm"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/backgroundLightGray"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/app_bar"
|
||||||
|
style="@style/Widget.MaterialComponents.Toolbar.Surface"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/backgroundLightGray"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
app:liftOnScroll="true">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:title="@string/details_manage_security"
|
||||||
|
app:navigationIcon="@drawable/ic_baseline_arrow_back_24" />
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/cl_details_confirm"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginBottom="33dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_long_tap_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:text="@string/details_manage_security_long_tap"
|
||||||
|
android:textSize="16sp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||||
|
android:id="@+id/radiobutton_long_tap"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_long_tap_description"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:paddingEnd="60dp"
|
||||||
|
android:textColor="@color/darkGray1"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tv_long_tap_title"
|
||||||
|
android:text="Caution: When having the switch on, all data will be encrypted and kept from being stolen."
|
||||||
|
android:textSize="13sp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/v_long_tap"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/tv_long_tap_title"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/tv_long_tap_description"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_passcode_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/v_long_tap"
|
||||||
|
android:text="@string/details_manage_security_passcode"
|
||||||
|
android:textSize="16sp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||||
|
android:id="@+id/radiobutton_passcode"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/v_passcode"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_passcode_description"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:paddingEnd="60dp"
|
||||||
|
android:textColor="@color/darkGray1"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tv_passcode_title"
|
||||||
|
android:text="Caution: When having the switch on, all data will be encrypted and kept from being stolen."
|
||||||
|
android:textSize="13sp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/v_passcode"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/tv_passcode_title"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/tv_passcode_description"/>
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_access_code_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/v_passcode"
|
||||||
|
android:text="@string/details_manage_security_access_code"
|
||||||
|
android:textSize="16sp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||||
|
android:id="@+id/radiobutton_access_code"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/v_access_code"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_access_code_description"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:paddingEnd="60dp"
|
||||||
|
android:textColor="@color/darkGray1"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tv_access_code_title"
|
||||||
|
android:text="Caution: When having the switch on, all data will be encrypted and kept from being stolen."
|
||||||
|
android:textSize="13sp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/v_access_code"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/tv_access_code_title"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/tv_access_code_description"/>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Guideline
|
||||||
|
android:id="@+id/guideline"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintGuide_percent="0.37" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btn_save_changes"
|
||||||
|
style="@style/TapBlackButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginStart="7dp"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:layout_marginEnd="30dp"
|
||||||
|
android:text="@string/details_save_changes"
|
||||||
|
app:icon="@drawable/ic_save"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
@ -86,6 +86,7 @@
|
||||||
<string name="details_toolbar_title">Details</string>
|
<string name="details_toolbar_title">Details</string>
|
||||||
<string name="details_notification_erase_wallet_not_allowed">Card settings prohibits from erasing wallet</string>
|
<string name="details_notification_erase_wallet_not_allowed">Card settings prohibits from erasing wallet</string>
|
||||||
<string name="details_notification_erase_wallet_not_possible">You balance on this wallet is not zero, or you have unconfirmed transactions</string>
|
<string name="details_notification_erase_wallet_not_possible">You balance on this wallet is not zero, or you have unconfirmed transactions</string>
|
||||||
|
<string name="details_notification_security_option_already_active">This is the currently active option</string>
|
||||||
<string name="details_card_id">Card ID</string>
|
<string name="details_card_id">Card ID</string>
|
||||||
<string name="details_issuer">Issuer</string>
|
<string name="details_issuer">Issuer</string>
|
||||||
<string name="details_signed_hashes">Signed</string>
|
<string name="details_signed_hashes">Signed</string>
|
||||||
|
|
@ -95,6 +96,13 @@
|
||||||
<string name="details_validate_card">Validate card</string>
|
<string name="details_validate_card">Validate card</string>
|
||||||
<string name="details_manage_security">Manage security</string>
|
<string name="details_manage_security">Manage security</string>
|
||||||
<string name="details_erase_wallet">Erase wallet</string>
|
<string name="details_erase_wallet">Erase wallet</string>
|
||||||
|
<string name="details_save_changes">Save changes</string>
|
||||||
|
<string name="details_manage_security_long_tap">Long Tap</string>
|
||||||
|
<string name="details_manage_security_passcode">Passcode</string>
|
||||||
|
<string name="details_manage_security_access_code">Access Code</string>
|
||||||
|
<string name="details_erase_wallet_warning">This action is irreversible. If, after deleting the wallet, someone sends funds to it, then you will not be able to withdraw them.</string>
|
||||||
|
<string name="details_manage_security_warning">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.
|
||||||
|
</string>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue