Updated on 2026-08-14

This commit is contained in:
Tangem 2020-05-02 15:37:37 +00:00
commit e10bb40e6d
21 changed files with 581 additions and 383 deletions

2
.gitignore vendored
View file

@ -16,7 +16,7 @@ local.properties
.idea/codeStyles
# LayoutInspector files
.captures
/captures
# OS-specific files
.DS_Store

View file

@ -12,6 +12,7 @@ data class NdefRecord(
URI, AAR, TEXT
}
@delegate:Transient
val valueInBytes: ByteArray by lazy { value.toByteArray() }
}

View file

@ -9,6 +9,11 @@ interface DefaultConverter<A, B> {
fun convert(from: A, default: B): B
}
interface TwoWayConverter<A, B> {
fun aToB(from: A): B
fun bToA(from: B): A
}
interface ItemsToModel<M> : DefaultConverter<List<Item>, M>
interface ModelToItems<M> : Converter<M, List<Item>>

View file

@ -1,5 +1,8 @@
package com.tangem.devkit.extensions
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import androidx.activity.ComponentActivity
import androidx.fragment.app.Fragment
@ -7,6 +10,13 @@ import androidx.fragment.app.Fragment
/**
[REDACTED_AUTHOR]
*/
fun Context.copyToClipboard(value: Any, label: String = "") {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager ?: return
val clip: ClipData = ClipData.newPlainText(label, value.toString())
clipboard.setPrimaryClip(clip)
}
fun Fragment.shareText(text: String) {
requireActivity().shareText(text)
}

View file

@ -1,139 +0,0 @@
package com.tangem.devkit.extensions
import android.app.Application
import android.content.Context
import com.tangem.commands.*
import com.tangem.commands.personalization.entities.CardConfig
import com.tangem.commands.personalization.entities.NdefRecord
import java.util.*
fun CardConfig.Companion.create(application: Application): CardConfig {
val preferences = application.getSharedPreferences("prefs", Context.MODE_PRIVATE)
val signingMethodMaskBuilder = SigningMethodMaskBuilder()
if (preferences.getBoolean("personalization_SigningMethod_0", false)) {
signingMethodMaskBuilder.add(SigningMethod.SignHash)
}
if (preferences.getBoolean("personalization_SigningMethod_1", false)) {
signingMethodMaskBuilder.add(SigningMethod.SignRaw)
}
if (preferences.getBoolean("personalization_SigningMethod_2", false)) {
signingMethodMaskBuilder.add(SigningMethod.SignHashValidateByIssuer)
}
if (preferences.getBoolean("personalization_SigningMethod_3", false)) {
signingMethodMaskBuilder.add(SigningMethod.SignRawValidateByIssuer)
}
if (preferences.getBoolean("personalization_SigningMethod_4", false)) {
signingMethodMaskBuilder.add(SigningMethod.SignHashValidateByIssuerWriteIssuerData)
}
if (preferences.getBoolean("personalization_SigningMethod_5", false)) {
signingMethodMaskBuilder.add(SigningMethod.SignRawValidateByIssuerWriteIssuerData)
}
if (preferences.getBoolean("personalization_SigningMethod_6", false)) {
signingMethodMaskBuilder.add(SigningMethod.SignHash)
}
val signingMethod = signingMethodMaskBuilder.build()
val isNote = preferences.getBoolean("personalization_ProductMask_IsNote", true)
val isTag = preferences.getBoolean("personalization_ProductMask_IsTag", false)
val isIdCard = preferences.getBoolean("personalization_ProductMask_IsIDCard", false)
val productMaskBuilder = ProductMaskBuilder()
if (isNote) productMaskBuilder.add(Product.Note)
if (isTag) productMaskBuilder.add(Product.Tag)
if (isIdCard) productMaskBuilder.add(Product.IdCard)
val productMask = productMaskBuilder.build()
var tokenSymbol: String? = null
var tokenContractAddress: String? = null
var tokenDecimal: Int? = null
if (preferences.getBoolean("personalization_isToken", false)) {
tokenSymbol = preferences.getString("personalization_token_symbol", "")
tokenContractAddress = preferences.getString("personalization_token_contract_address", "")
tokenDecimal = preferences.getString("personalization_token_decimal", "")!!.toInt()
}
val cardData = CardData(
blockchainName = preferences.getString("personalization_Blockchain", "BTC"),
batchId = preferences.getString("personalization_card_batch", "FFFF"),
productMask = productMask,
tokenSymbol = tokenSymbol,
tokenContractAddress = tokenContractAddress,
tokenDecimal = tokenDecimal,
issuerName = null,
manufactureDateTime = Calendar.getInstance().time,
manufacturerSignature = null)
val ndefAar = preferences.getString("personalization_NDEF_AAR", "Release APP")
val ndefUri = preferences.getString("personalization_NDEF_URI", "https://tangem.com")
val ndefs = mutableListOf<NdefRecord>()
if (!ndefUri.isNullOrEmpty()) {
ndefs.add(NdefRecord(NdefRecord.Type.URI, ndefUri))
}
if (ndefAar != "None") {
val type = NdefRecord.Type.AAR
val value = when (ndefAar) {
"Debug APP" -> {
"com.tangem.wallet.debug"
}
"Release APP" -> {
"com.tangem.wallet"
}
"--- CUSTOM ---" -> {
preferences.getString("personalization_NDEF_CUSTOM_AAR", "com.tangem.wallet")!!
}
else -> ""
}
ndefs.add(NdefRecord(type, value))
}
return CardConfig(
cardData = cardData,
curveID = EllipticCurve.byName(preferences.getString("personalization_CurveId", "secp256k1")!!)
?: EllipticCurve.Secp256k1,
signingMethods = signingMethod,
createWallet = preferences.getBoolean("personalization_CreateWallet", true),
maxSignatures = preferences.getString("personalization_MaxSignatures", "1000")!!.toInt(),
isReusable = preferences.getBoolean("personalization_SettingsMask_IsReusable", true),
protocolAllowUnencrypted = preferences.getBoolean("personalization_SettingsMask_AllowEncryption_None", true),
protocolAllowStaticEncryption = preferences.getBoolean("personalization_SettingsMask_AllowEncryption_Fast", true),
useActivation = preferences.getBoolean("personalization_SettingsMask_NeedActivation", false),
useOneCommandAtTime = preferences.getBoolean("personalization_SettingsMask_OneApduAtOnce", false),
useCvc = preferences.getBoolean("personalization_SettingsMask_UseCVC", false),
useBlock = preferences.getBoolean("personalization_SettingsMask_UseBlock", false),
allowSwapPin = preferences.getBoolean("personalization_SettingsMask_AllowSwapPIN", true),
allowSwapPin2 = preferences.getBoolean("personalization_SettingsMask_AllowSwapPIN2", true),
useNdef = preferences.getBoolean("personalization_SettingsMask_UseNDEF", true),
useDynamicNdef = preferences.getBoolean("personalization_SettingsMask_UseDynamicNDEF", true),
protectIssuerDataAgainstReplay = preferences.getBoolean("personalization_SettingsMask_ProtectIssuerDataAgainstReplay", true),
forbidDefaultPin = preferences.getBoolean("personalization_SettingsMask_ForbidDefaultPIN", false),
smartSecurityDelay = preferences.getBoolean("personalization_SettingsMask_SmartSecurityDelay", false),
pauseBeforePin2 = preferences.getString("personalization_PauseBeforePIN2", "15")!!.toInt() * 1000,
allowSelectBlockchain = preferences.getBoolean("personalization_SettingsMask_AllowSelectBlockchain", false),
forbidPurgeWallet = preferences.getBoolean("personalization_SettingsMask_ForbidPurgeWallet", false)
?: false,
disablePrecomputedNdef = preferences.getBoolean("personalization_SettingsMask_DisablePrecomputedNDEF", false)
?: false,
skipSecurityDelayIfValidatedByIssuer = preferences.getBoolean("personalization_SettingsMask_SkipSecurityDelayIfValidatedByIssuer", true),
skipCheckPIN2andCVCIfValidatedByIssuer = preferences.getBoolean("personalization_SettingsMask_SkipCheckPIN2andCVCIfValidatedByIssuer", true),
skipSecurityDelayIfValidatedByLinkedTerminal = preferences.getBoolean("personalization_SettingsMask_SkipSecurityDelayIfValidatedByLinkedTerminal", true),
restrictOverwriteIssuerDataEx = preferences.getBoolean("personalization_SettingsMask_RestrictOverwriteIssuerDataEx", true),
requireTerminalTxSignature = preferences.getBoolean("personalization_SettingsMask_RequireTerminalTxSignature", false),
requireTerminalCertSignature = preferences.getBoolean("personalization_SettingsMask_RequireTerminalCertSignature", false),
checkPin3onCard = preferences.getBoolean("personalization_SettingsMask_CheckPIN3onCard", true),
cvc = preferences.getString("personalization_cvc", "000") ?: "000",
pin = preferences.getString("personalization_pin", "000000") ?: "000000",
pin2 = preferences.getString("personalization_pin2", "000") ?: "000",
pin3 = preferences.getString("personalization_pin3", "123") ?: "123",
hexCrExKey = preferences.getString("personalization_CrEx_Key", "00112233445566778899AABBCCDDEEFFFFEEDDCCBBAA998877665544332211000000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF"),
ndefRecords = ndefs
)
}

View file

@ -11,9 +11,10 @@ import com.tangem.devkit.ucase.tunnel.ActionView
import com.tangem.devkit.ucase.tunnel.ItemError
import com.tangem.devkit.ucase.variants.personalize.CardNumberId
import com.tangem.devkit.ucase.variants.personalize.converter.PersonalizationConfigConverter
import com.tangem.devkit.ucase.variants.personalize.converter.PersonalizationConfigToCardConfig
import com.tangem.devkit.ucase.variants.personalize.converter.PersonalizationJsonConverter
import com.tangem.devkit.ucase.variants.personalize.dto.DefaultPersonalizationParams
import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationConfig
import com.tangem.devkit.ucase.variants.personalize.dto.toCardConfig
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
/**
@ -37,10 +38,10 @@ class PersonalizeAction : BaseAction() {
val acquirer = DefaultPersonalizationParams.acquirer()
val manufacturer = DefaultPersonalizationParams.manufacturer()
val personalizeConfig = PersonalizationConfigConverter().convert(itemList, PersonalizationConfig.default())
val cardConfig = PersonalizationConfigToCardConfig().convert(personalizeConfig)
val config = PersonalizationConfigConverter().convert(itemList, PersonalizationConfig.default())
val jsonDto = PersonalizationJsonConverter().bToA(config)
attrs.tangemSdk.personalize(cardConfig, issuer, manufacturer, acquirer) {
attrs.tangemSdk.personalize(jsonDto.toCardConfig(), issuer, manufacturer, acquirer) {
handleResult(payload, it, null, attrs, callback)
}
}

View file

@ -7,7 +7,10 @@ import com.tangem.devkit.commons.Store
import com.tangem.devkit.ucase.domain.actions.PersonalizeAction
import com.tangem.devkit.ucase.domain.paramsManager.ActionCallback
import com.tangem.devkit.ucase.variants.personalize.converter.PersonalizationConfigConverter
import com.tangem.devkit.ucase.variants.personalize.converter.PersonalizationJsonConverter
import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationConfig
import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationJson
import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
/**
[REDACTED_AUTHOR]
@ -27,6 +30,27 @@ class PersonalizationItemsManager(
action.executeMainAction(this, getAttrsForAction(tangemSdk), callback)
}
fun importJsonConfig(jsonString: String) {
if (jsonString.isEmpty()) return
val jsonDto = try {
PersonalizationJson.getJsonConverter().fromJson(jsonString, PersonalizationJson::class.java)
} catch (ex: Exception) {
Log.e(this, "Can't convert imported string to Json object. Error: $ex")
return
}
val config = PersonalizationJsonConverter().aToB(jsonDto)
updateByItemList(converter.convert(config))
}
fun exportJsonConfig(): String {
val config = converter.convert(itemList, PersonalizationConfig.default())
val jsonDto = PersonalizationJsonConverter().bToA(config)
val jsonString = PersonalizationJson.getJsonConverter().toJson(jsonDto)
return jsonString
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
val config = converter.convert(itemList, PersonalizationConfig.default())

View file

@ -17,7 +17,6 @@ class PersonalizationResources() {
initCommon(holder)
initSigningMethod(holder)
initSignHashExProp(holder)
initDenomination(holder)
initToken(holder)
initProductMask(holder)
initSettingsMask(holder)
@ -72,11 +71,6 @@ class PersonalizationResources() {
holder.register(SignHashExPropId.CheckPin3, Resources(R.string.pers_item_check_pin3_on_card, R.string.info_pers_item_check_pin3_on_card))
}
private fun initDenomination(holder: TypedHolder<Id, Resources>) {
holder.register(DenominationId.WriteOnPersonalize, Resources(R.string.pers_item_write_on_personalize, R.string.info_pers_item_write_on_personalize))
holder.register(DenominationId.Denomination, Resources(R.string.pers_item_denomination, R.string.info_pers_item_denomination))
}
private fun initToken(holder: TypedHolder<Id, Resources>) {
holder.register(TokenId.ItsToken, Resources(R.string.pers_item_its_token, R.string.info_pers_item_its_token))
holder.register(TokenId.Symbol, Resources(R.string.pers_item_symbol, R.string.info_pers_item_symbol))

View file

@ -54,11 +54,6 @@ enum class SignHashExPropId : PersonalizationId {
CheckPin3,
}
enum class DenominationId : PersonalizationId {
WriteOnPersonalize,
Denomination,
}
enum class TokenId : PersonalizationId {
ItsToken,
Symbol,

View file

@ -5,6 +5,7 @@ import com.tangem.devkit._arch.structure.Id
import com.tangem.devkit._arch.structure.abstraction.KeyValue
import com.tangem.devkit.ucase.variants.personalize.*
import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationConfig
import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationJson
import ru.dev.gbixahue.eu4d.lib.kotlin.common.BaseTypedHolder
/**
@ -16,9 +17,9 @@ class ConfigValuesHolder : BaseTypedHolder<Id, Value>() {
fun init(default: PersonalizationConfig) {
register(CardNumberId.Series, Value(default.series))
register(CardNumberId.Number, Value(default.startNumber))
register(CardNumberId.BatchId, Value(default.batchId))
register(CardNumberId.BatchId, Value(default.cardData.batch))
register(CommonId.Curve, Value(default.curveID, Helper.listOfCurves()))
register(CommonId.Blockchain, Value(default.blockchain, Helper.listOfBlockchain()))
register(CommonId.Blockchain, Value(default.cardData.blockchain, Helper.listOfBlockchain()))
register(CommonId.BlockchainCustom, Value(default.blockchainCustom))
register(CommonId.MaxSignatures, Value(default.MaxSignatures))
register(CommonId.CreateWallet, Value(default.createWallet))
@ -34,12 +35,10 @@ class ConfigValuesHolder : BaseTypedHolder<Id, Value>() {
register(SignHashExPropId.RequireTerminalCertSig, Value(default.requireTerminalCertSignature))
register(SignHashExPropId.RequireTerminalTxSig, Value(default.requireTerminalTxSignature))
register(SignHashExPropId.CheckPin3, Value(default.checkPIN3onCard))
register(DenominationId.WriteOnPersonalize, Value(default.writeOnPersonalization))
register(DenominationId.Denomination, Value(default.denomination))
register(TokenId.ItsToken, Value(default.itsToken))
register(TokenId.Symbol, Value(default.symbol))
register(TokenId.ContractAddress, Value(default.contractAddress))
register(TokenId.Decimal, Value(default.decimal))
register(TokenId.Symbol, Value(default.cardData.token_symbol))
register(TokenId.ContractAddress, Value(default.cardData.token_contract_address))
register(TokenId.Decimal, Value(default.cardData.token_decimal))
register(ProductMaskId.Note, Value(default.cardData.product_note))
register(ProductMaskId.Tag, Value(default.cardData.product_tag))
register(ProductMaskId.IdCard, Value(default.cardData.product_id_card))
@ -49,7 +48,7 @@ class ConfigValuesHolder : BaseTypedHolder<Id, Value>() {
register(SettingsMaskId.ForbidPurge, Value(default.forbidPurgeWallet))
register(SettingsMaskId.AllowSelectBlockchain, Value(default.allowSelectBlockchain))
register(SettingsMaskId.UseBlock, Value(default.useBlock))
register(SettingsMaskId.OneApdu, Value(default.oneApdu))
register(SettingsMaskId.OneApdu, Value(default.useOneCommandAtTime))
register(SettingsMaskId.UseCvc, Value(default.useCVC))
register(SettingsMaskId.AllowSwapPin, Value(default.allowSwapPIN))
register(SettingsMaskId.AllowSwapPin2, Value(default.allowSwapPIN2))
@ -94,7 +93,7 @@ internal class Helper {
fun listOfBlockchain(): List<KeyValue> {
return mutableListOf(
KeyValue("--- CUSTOM ---", ""),
KeyValue(PersonalizationJson.CUSTOM, PersonalizationJson.CUSTOM),
KeyValue("BTC", "BTC"),
KeyValue("BTC/test", "BTC/test"),
KeyValue("ETH", "ETH"),
@ -115,7 +114,7 @@ internal class Helper {
fun aarList(): List<KeyValue> {
return mutableListOf(
KeyValue("--- CUSTOM ---", ""),
KeyValue(PersonalizationJson.CUSTOM, PersonalizationJson.CUSTOM),
KeyValue("Release APP", "com.tangem.wallet"),
KeyValue("Debug APP", "com.tangem.wallet.debug"),
KeyValue("None", "")

View file

@ -17,7 +17,7 @@ class ItemTypes {
CommonId.CreateWallet, SigningMethodId.SignTx, SigningMethodId.SignTxRaw, SigningMethodId.SignValidatedTx,
SigningMethodId.SignValidatedTxRaw, SigningMethodId.SignValidatedTxIssuer,
SigningMethodId.SignValidatedTxRawIssuer, SigningMethodId.SignExternal, SignHashExPropId.RequireTerminalCertSig,
SignHashExPropId.RequireTerminalTxSig, SignHashExPropId.CheckPin3, DenominationId.WriteOnPersonalize, TokenId.ItsToken,
SignHashExPropId.RequireTerminalTxSig, SignHashExPropId.CheckPin3, TokenId.ItsToken,
ProductMaskId.Note, ProductMaskId.Tag, ProductMaskId.IdCard, ProductMaskId.IdIssuerCard, SettingsMaskId.IsReusable, SettingsMaskId.NeedActivation,
SettingsMaskId.ForbidPurge, SettingsMaskId.AllowSelectBlockchain, SettingsMaskId.UseBlock, SettingsMaskId.OneApdu,
SettingsMaskId.UseCvc, SettingsMaskId.AllowSwapPin, SettingsMaskId.AllowSwapPin2, SettingsMaskId.ForbidDefaultPin,
@ -34,7 +34,7 @@ class ItemTypes {
)
val numberList = mutableListOf(
CardNumberId.Number, CommonId.MaxSignatures, SignHashExPropId.PinLessFloorLimit, DenominationId.Denomination, TokenId.Decimal
CardNumberId.Number, CommonId.MaxSignatures, SignHashExPropId.PinLessFloorLimit, TokenId.Decimal
)
val hiddenList = mutableListOf<Id>(

View file

@ -52,9 +52,9 @@ class ItemsToPersonalizationConfig : ItemsToModel<PersonalizationConfig> {
val export = PersonalizationConfig()
export.series = getTyped(CardNumberId.Series)
export.startNumber = getTyped(CardNumberId.Number)
export.batchId = getTyped(CardNumberId.BatchId)
export.cardData.batch = getTyped(CardNumberId.BatchId)
export.curveID = getTyped(CommonId.Curve)
export.blockchain = getTyped(CommonId.Blockchain)
export.cardData.blockchain = getTyped(CommonId.Blockchain)
export.blockchainCustom = getTyped(CommonId.BlockchainCustom)
export.MaxSignatures = getTyped(CommonId.MaxSignatures)
export.createWallet = getTyped(CommonId.CreateWallet)
@ -70,12 +70,10 @@ class ItemsToPersonalizationConfig : ItemsToModel<PersonalizationConfig> {
export.requireTerminalCertSignature = getTyped(SignHashExPropId.RequireTerminalCertSig)
export.requireTerminalTxSignature = getTyped(SignHashExPropId.RequireTerminalTxSig)
export.checkPIN3onCard = getTyped(SignHashExPropId.CheckPin3)
export.writeOnPersonalization = getTyped(DenominationId.WriteOnPersonalize)
export.denomination = getTyped(DenominationId.Denomination)
export.itsToken = getTyped(TokenId.ItsToken)
export.symbol = getTyped(TokenId.Symbol)
export.contractAddress = getTyped(TokenId.ContractAddress)
export.decimal = getTyped(TokenId.Decimal)
export.cardData.token_symbol = getTyped(TokenId.Symbol)
export.cardData.token_contract_address = getTyped(TokenId.ContractAddress)
export.cardData.token_decimal = getTyped(TokenId.Decimal)
export.cardData = export.cardData.apply { this.product_note = getTyped(ProductMaskId.Note) }
export.cardData = export.cardData.apply { this.product_tag = getTyped(ProductMaskId.Tag) }
export.cardData = export.cardData.apply { this.product_id_card = getTyped(ProductMaskId.IdCard) }
@ -85,7 +83,7 @@ class ItemsToPersonalizationConfig : ItemsToModel<PersonalizationConfig> {
export.forbidPurgeWallet = getTyped(SettingsMaskId.ForbidPurge)
export.allowSelectBlockchain = getTyped(SettingsMaskId.AllowSelectBlockchain)
export.useBlock = getTyped(SettingsMaskId.UseBlock)
export.oneApdu = getTyped(SettingsMaskId.OneApdu)
export.useOneCommandAtTime = getTyped(SettingsMaskId.OneApdu)
export.useCVC = getTyped(SettingsMaskId.UseCvc)
export.allowSwapPIN = getTyped(SettingsMaskId.AllowSwapPin)
export.allowSwapPIN2 = getTyped(SettingsMaskId.AllowSwapPin2)
@ -138,14 +136,13 @@ class PersonalizationConfigToItems : ModelToItems<PersonalizationConfig> {
blocList.add(cardNumber())
blocList.add(common())
blocList.add(signingMethod())
// blocList.add(signHashExProperties())
// blocList.add(denomination())
// blocList.add(token())
// blocList.add(productMask())
// blocList.add(settingsMask())
// blocList.add(settingsMaskProtocolEnc())
// blocList.add(settingsMaskNdef())
// blocList.add(pins())
blocList.add(signHashExProperties())
blocList.add(token())
blocList.add(productMask())
blocList.add(settingsMask())
blocList.add(settingsMaskProtocolEnc())
blocList.add(settingsMaskNdef())
blocList.add(pins())
blocList.iterate {
if (itemTypes.hiddenList.contains(it.id)) {
it.viewModel.viewState.isVisibleState.value = false
@ -203,15 +200,6 @@ class PersonalizationConfigToItems : ModelToItems<PersonalizationConfig> {
return block
}
private fun denomination(): ItemGroup {
val block = createGroup(BlockId.Denomination)
mutableListOf(
DenominationId.WriteOnPersonalize,
DenominationId.Denomination
).forEach { createItem(block, it) }
return block
}
private fun token(): ItemGroup {
val block = createGroup(BlockId.Token)
mutableListOf(

View file

@ -1,125 +0,0 @@
package com.tangem.devkit.ucase.variants.personalize.converter
import com.tangem.commands.*
import com.tangem.commands.personalization.entities.CardConfig
import com.tangem.commands.personalization.entities.NdefRecord
import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationConfig
import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter
import java.util.*
class PersonalizationConfigToCardConfig : Converter<PersonalizationConfig, CardConfig> {
override fun convert(from: PersonalizationConfig): CardConfig {
val signingMethodMaskBuilder = SigningMethodMaskBuilder()
if (from.SigningMethod0) {
signingMethodMaskBuilder.add(SigningMethod.SignHash)
}
if (from.SigningMethod1) {
signingMethodMaskBuilder.add(SigningMethod.SignRaw)
}
if (from.SigningMethod2) {
signingMethodMaskBuilder.add(SigningMethod.SignHashValidateByIssuer)
}
if (from.SigningMethod3) {
signingMethodMaskBuilder.add(SigningMethod.SignRawValidateByIssuer)
}
if (from.SigningMethod4) {
signingMethodMaskBuilder.add(SigningMethod.SignHashValidateByIssuerWriteIssuerData)
}
if (from.SigningMethod5) {
signingMethodMaskBuilder.add(SigningMethod.SignRawValidateByIssuerWriteIssuerData)
}
if (from.SigningMethod6) {
signingMethodMaskBuilder.add(SigningMethod.SignHash)
}
val signingMethod = signingMethodMaskBuilder.build()
val isNote = from.cardData.product_note
val isTag = from.cardData.product_tag
val isIdCard = from.cardData.product_id_card
val isIdIssuer = from.cardData.product_id_issuer
val productMaskBuilder = ProductMaskBuilder()
if (isNote) productMaskBuilder.add(com.tangem.commands.Product.Note)
if (isTag) productMaskBuilder.add(com.tangem.commands.Product.Tag)
if (isIdCard) productMaskBuilder.add(com.tangem.commands.Product.IdCard)
if (isIdIssuer) productMaskBuilder.add(com.tangem.commands.Product.IdIssuer)
val productMask = productMaskBuilder.build()
var tokenSymbol: String? = null
var tokenContractAddress: String? = null
var tokenDecimal: Int? = null
if (from.itsToken) {
tokenSymbol = from.symbol
tokenContractAddress = from.contractAddress
tokenDecimal = from.decimal.toInt()
}
val blockchain = if (from.blockchain.isNotEmpty()) from.blockchain else from.blockchainCustom
val cardData = CardData(
blockchainName = blockchain,
batchId = from.batchId,
productMask = productMask,
tokenSymbol = tokenSymbol,
tokenContractAddress = tokenContractAddress,
tokenDecimal = tokenDecimal,
issuerName = null,
manufactureDateTime = Calendar.getInstance().time,
manufacturerSignature = null)
val ndefs = mutableListOf<NdefRecord>()
if (from.uri.isNotEmpty()) {
ndefs.add(NdefRecord(NdefRecord.Type.URI, from.uri))
}
when (from.aar) {
"None" -> null
"--- CUSTOM ---" -> NdefRecord(NdefRecord.Type.AAR, from.aarCustom)
else -> NdefRecord(NdefRecord.Type.AAR, from.aar)
}?.let { ndefs.add(it) }
return CardConfig(
"Tangem",
"Tangem Test",
from.series,
from.startNumber,
1000,
from.PIN,
from.PIN2,
from.PIN3,
from.hexCrExKey,
from.CVC,
from.pauseBeforePIN2.toInt(),
from.smartSecurityDelay,
EllipticCurve.byName(from.curveID) ?: EllipticCurve.Secp256k1,
signingMethod,
from.MaxSignatures.toInt(),
from.isReusable,
from.allowSwapPIN,
from.allowSwapPIN2,
from.useActivation,
from.useCVC,
from.useNDEF,
from.useDynamicNDEF,
from.oneApdu,
from.useBlock,
from.allowSelectBlockchain,
from.forbidPurgeWallet,
from.protocolAllowUnencrypted,
from.protocolAllowStaticEncryption,
from.protectIssuerDataAgainstReplay,
from.forbidDefaultPIN,
from.disablePrecomputedNDEF,
from.skipSecurityDelayIfValidatedByIssuer,
from.skipCheckPIN2andCVCIfValidatedByIssuer,
from.skipSecurityDelayIfValidatedByLinkedTerminal,
from.restrictOverwriteIssuerDataEx,
from.requireTerminalTxSignature,
from.requireTerminalCertSignature,
from.checkPIN3onCard,
from.createWallet,
cardData,
ndefs
)
}
}

View file

@ -0,0 +1,203 @@
package com.tangem.devkit.ucase.variants.personalize.converter
import com.tangem.commands.EllipticCurve
import com.tangem.commands.SigningMethod
import com.tangem.commands.SigningMethodMask
import com.tangem.commands.personalization.entities.NdefRecord
import com.tangem.devkit._arch.structure.abstraction.TwoWayConverter
import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationConfig
import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationJson
import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter
/**
[REDACTED_AUTHOR]
*/
class PersonalizationJsonConverter : TwoWayConverter<PersonalizationJson, PersonalizationConfig> {
override fun aToB(from: PersonalizationJson): PersonalizationConfig = JsonToConfig().convert(from)
override fun bToA(from: PersonalizationConfig): PersonalizationJson = ConfigToJson().convert(from)
}
internal class JsonToConfig : Converter<PersonalizationJson, PersonalizationConfig> {
override fun convert(jsonDto: PersonalizationJson): PersonalizationConfig {
val config = PersonalizationConfig.default()
config.apply {
series = jsonDto.series
startNumber = jsonDto.startNumber
curveID = EllipticCurve.byName(jsonDto.curveID)?.curve ?: ""
blockchainCustom = ""
MaxSignatures = jsonDto.MaxSignatures
createWallet = jsonDto.createWallet != 0L
hexCrExKey = jsonDto.hexCrExKey
requireTerminalTxSignature = jsonDto.requireTerminalTxSignature
requireTerminalCertSignature = jsonDto.requireTerminalCertSignature
checkPIN3onCard = jsonDto.checkPIN3onCard
isReusable = jsonDto.isReusable
useActivation = jsonDto.useActivation
forbidPurgeWallet = jsonDto.forbidPurgeWallet
allowSelectBlockchain = jsonDto.allowSelectBlockchain
useBlock = jsonDto.useBlock
useOneCommandAtTime = jsonDto.useOneCommandAtTime
useCVC = jsonDto.useCVC
allowSwapPIN = jsonDto.allowSwapPIN
allowSwapPIN2 = jsonDto.allowSwapPIN2
forbidDefaultPIN = jsonDto.forbidDefaultPIN
smartSecurityDelay = jsonDto.smartSecurityDelay
protectIssuerDataAgainstReplay = jsonDto.protectIssuerDataAgainstReplay
skipSecurityDelayIfValidatedByIssuer = jsonDto.skipSecurityDelayIfValidatedByIssuer
skipCheckPIN2andCVCIfValidatedByIssuer = jsonDto.skipCheckPIN2andCVCIfValidatedByIssuer
skipSecurityDelayIfValidatedByLinkedTerminal = jsonDto.skipSecurityDelayIfValidatedByLinkedTerminal
restrictOverwriteIssuerDataEx = jsonDto.restrictOverwriteIssuerDataEx
protocolAllowUnencrypted = jsonDto.protocolAllowUnencrypted
protocolAllowStaticEncryption = jsonDto.protocolAllowStaticEncryption
useNDEF = jsonDto.useNDEF
useDynamicNDEF = jsonDto.useDynamicNDEF
disablePrecomputedNDEF = jsonDto.disablePrecomputedNDEF
PIN = jsonDto.PIN
PIN2 = jsonDto.PIN2
PIN3 = jsonDto.PIN3
CVC = jsonDto.CVC
pauseBeforePIN2 = jsonDto.pauseBeforePIN2
count = jsonDto.count
issuerName = jsonDto.issuerName
issuerData = jsonDto.issuerData
// numberFormat = from.numberFormat
// pinLessFloorLimit = 100000L
}
fillCardData(jsonDto, config)
fillSigningMethod(jsonDto, config)
fillNdef(jsonDto, config)
return config
}
private fun fillCardData(jsonDto: PersonalizationJson, config: PersonalizationConfig) {
val jsonCardData = jsonDto.cardData
// copy whole object and then checking tricky places
config.cardData = jsonCardData
config.itsToken = jsonCardData.token_contract_address.isNotEmpty() || jsonCardData.token_symbol.isNotEmpty()
val selectedBlockchain = Helper.listOfBlockchain().firstOrNull { it.value == jsonCardData.blockchain }
if (selectedBlockchain == null) {
config.cardData.blockchain = PersonalizationJson.CUSTOM
config.blockchainCustom = jsonCardData.blockchain
}
}
private fun fillSigningMethod(jsonDto: PersonalizationJson, config: PersonalizationConfig) {
val mask = SigningMethodMask(jsonDto.SigningMethod.toInt())
if (mask.contains(SigningMethod.SignHash)) config.SigningMethod0 = true
if (mask.contains(SigningMethod.SignRaw)) config.SigningMethod1 = true
if (mask.contains(SigningMethod.SignHashValidateByIssuer)) config.SigningMethod2 = true
if (mask.contains(SigningMethod.SignRawValidateByIssuer)) config.SigningMethod3 = true
if (mask.contains(SigningMethod.SignHashValidateByIssuerWriteIssuerData)) config.SigningMethod4 = true
if (mask.contains(SigningMethod.SignRawValidateByIssuerWriteIssuerData)) config.SigningMethod5 = true
}
private fun fillNdef(jsonDto: PersonalizationJson, config: PersonalizationConfig) {
jsonDto.ndef.forEach { record ->
when (record.type) {
NdefRecord.Type.URI -> config.uri = record.value
NdefRecord.Type.AAR -> config.aar = record.value
NdefRecord.Type.TEXT -> {
}
}
}
val selectedAar = Helper.aarList().firstOrNull { it.value == config.aar }
if (selectedAar == null) {
config.aarCustom = config.aar
config.aar = ""
}
}
}
internal class ConfigToJson : Converter<PersonalizationConfig, PersonalizationJson> {
override fun convert(from: PersonalizationConfig): PersonalizationJson {
val jsonDto = PersonalizationJson()
jsonDto.apply {
releaseVersion = false
issuerName = from.issuerName
series = from.series
startNumber = from.startNumber
count = from.count
PIN = from.PIN
PIN2 = from.PIN2
PIN3 = from.PIN3
hexCrExKey = from.hexCrExKey
CVC = from.CVC
pauseBeforePIN2 = from.pauseBeforePIN2
smartSecurityDelay = from.smartSecurityDelay
curveID = from.curveID
MaxSignatures = from.MaxSignatures
isReusable = from.isReusable
allowSwapPIN = from.allowSwapPIN
allowSwapPIN2 = from.allowSwapPIN2
useActivation = from.useActivation
useCVC = from.useCVC
useNDEF = from.useNDEF
useDynamicNDEF = from.useDynamicNDEF
useOneCommandAtTime = from.useOneCommandAtTime
useBlock = from.useBlock
allowSelectBlockchain = from.allowSelectBlockchain
forbidPurgeWallet = from.forbidPurgeWallet
protocolAllowUnencrypted = from.protocolAllowUnencrypted
protocolAllowStaticEncryption = from.protocolAllowStaticEncryption
protectIssuerDataAgainstReplay = from.protectIssuerDataAgainstReplay
forbidDefaultPIN = from.forbidDefaultPIN
disablePrecomputedNDEF = from.disablePrecomputedNDEF
skipSecurityDelayIfValidatedByIssuer = from.skipSecurityDelayIfValidatedByIssuer
skipCheckPIN2andCVCIfValidatedByIssuer = from.skipCheckPIN2andCVCIfValidatedByIssuer
skipSecurityDelayIfValidatedByLinkedTerminal = from.skipSecurityDelayIfValidatedByLinkedTerminal
restrictOverwriteIssuerDataEx = from.restrictOverwriteIssuerDataEx
requireTerminalTxSignature = from.requireTerminalTxSignature
requireTerminalCertSignature = from.requireTerminalCertSignature
checkPIN3onCard = from.checkPIN3onCard
createWallet = if (from.createWallet) 1 else 0
issuerData = from.issuerData
// numberFormat = from.numberFormat
// pinLessFloorLimit = 100000L
}
fillCardData(from, jsonDto)
fillSigningMethod(from, jsonDto)
fillNdef(from, jsonDto)
return jsonDto
}
private fun fillCardData(config: PersonalizationConfig, jsonDto: PersonalizationJson) {
jsonDto.cardData = config.cardData
if (config.cardData.blockchain == PersonalizationJson.CUSTOM) {
jsonDto.cardData.blockchain = config.blockchainCustom
}
if (config.itsToken) {
jsonDto.cardData.token_contract_address = config.cardData.token_contract_address
jsonDto.cardData.token_symbol = config.cardData.token_symbol
jsonDto.cardData.token_decimal = config.cardData.token_decimal
} else {
jsonDto.cardData.token_contract_address = ""
jsonDto.cardData.token_symbol = ""
jsonDto.cardData.token_decimal = 0
}
}
private fun fillSigningMethod(config: PersonalizationConfig, jsonDto: PersonalizationJson) {
jsonDto.SigningMethod = PersonalizationConfig.makeSigningMethodMask(config).rawValue.toLong()
}
private fun fillNdef(config: PersonalizationConfig, jsonDto: PersonalizationJson) {
fun add(value: String, type: NdefRecord.Type) {
if (value.isNotEmpty()) jsonDto.ndef.add(NdefRecord(type, value))
}
if (config.aarCustom.isNotEmpty()) add(config.aarCustom, NdefRecord.Type.AAR)
else add(config.aar, NdefRecord.Type.AAR)
add(config.uri, NdefRecord.Type.URI)
}
}

View file

@ -1,6 +1,9 @@
package com.tangem.devkit.ucase.variants.personalize.dto
import com.tangem.commands.EllipticCurve
import com.tangem.commands.SigningMethod
import com.tangem.commands.SigningMethodMask
import com.tangem.commands.SigningMethodMaskBuilder
/**
[REDACTED_AUTHOR]
@ -10,11 +13,9 @@ class PersonalizationConfig {
// Card number
var series = ""
var startNumber: Long = 0
var batchId = ""
// Common
var curveID = ""
var blockchain = ""
var blockchainCustom = ""
var MaxSignatures: Long = 0
var createWallet = false
@ -35,16 +36,10 @@ class PersonalizationConfig {
var requireTerminalCertSignature = false
var checkPIN3onCard = false
// Denomination
var writeOnPersonalization = false
var denomination: Long = 0
// Token
var itsToken = false
var symbol = ""
var contractAddress = ""
var decimal: Long = 0
// Product mask
var cardData = CardData()
// Settings mask
@ -53,7 +48,7 @@ class PersonalizationConfig {
var forbidPurgeWallet = false
var allowSelectBlockchain = false
var useBlock = false
var oneApdu = false
var useOneCommandAtTime = false
var useCVC = false
var allowSwapPIN = false
var allowSwapPIN2 = false
@ -69,6 +64,7 @@ class PersonalizationConfig {
var protocolAllowUnencrypted = false
var protocolAllowStaticEncryption = false
// Settings mask
var useNDEF = false
var useDynamicNDEF = false
var disablePrecomputedNDEF = false
@ -83,17 +79,20 @@ class PersonalizationConfig {
var CVC = ""
var pauseBeforePIN2: Long = 0
var count: Long = 0
var issuerName = ""
var issuerData = null
companion object {
fun default(): PersonalizationConfig {
return PersonalizationConfig().apply {
// Card number
series = "BB"
startNumber = 300000000000L
batchId = "ffff"
// Common
curveID = EllipticCurve.Secp256k1.curve
blockchain = "ETH"
blockchainCustom = ""
MaxSignatures = 999999L
createWallet = true
@ -114,17 +113,10 @@ class PersonalizationConfig {
requireTerminalCertSignature = false
checkPIN3onCard = true
// Denomination
writeOnPersonalization = false
denomination = 1000000L
// Token
itsToken = false
symbol = ""
contractAddress = ""
decimal = 0L
cardData = CardData()
cardData = CardData.default()
// Settings mask
isReusable = true
@ -132,7 +124,7 @@ class PersonalizationConfig {
forbidPurgeWallet = false
allowSelectBlockchain = false
useBlock = false
oneApdu = false
useOneCommandAtTime = false
useCVC = false
allowSwapPIN = true
allowSwapPIN2 = true
@ -161,17 +153,67 @@ class PersonalizationConfig {
PIN3 = ""
CVC = "000"
pauseBeforePIN2 = 5000L
count = 1050
issuerName = "TANGEM"
issuerData = null
}
}
fun makeSigningMethodMask(from: PersonalizationConfig): SigningMethodMask {
val signingMethodMaskBuilder = SigningMethodMaskBuilder()
if (from.SigningMethod0) {
signingMethodMaskBuilder.add(SigningMethod.SignHash)
}
if (from.SigningMethod1) {
signingMethodMaskBuilder.add(SigningMethod.SignRaw)
}
if (from.SigningMethod2) {
signingMethodMaskBuilder.add(SigningMethod.SignHashValidateByIssuer)
}
if (from.SigningMethod3) {
signingMethodMaskBuilder.add(SigningMethod.SignRawValidateByIssuer)
}
if (from.SigningMethod4) {
signingMethodMaskBuilder.add(SigningMethod.SignHashValidateByIssuerWriteIssuerData)
}
if (from.SigningMethod5) {
signingMethodMaskBuilder.add(SigningMethod.SignRawValidateByIssuerWriteIssuerData)
}
if (from.SigningMethod6) {
signingMethodMaskBuilder.add(SigningMethod.SignHash)
}
return signingMethodMaskBuilder.build()
}
}
}
class CardData {
var date = "2020-02-17"
var batch = "FF87"
var blockchain = "IROHA"
var product_note = true
var date = ""
var batch = ""
var blockchain = ""
var token_symbol = ""
var token_contract_address = ""
var token_decimal: Long = 0
var product_note = false
var product_tag = false
var product_id_card = false
var product_id_issuer = false
companion object {
fun default(): CardData {
return CardData().apply {
date = "2020-02-17"
batch = "FFFF"
blockchain = "ETH"
token_symbol = ""
token_contract_address = ""
token_decimal = 0
product_note = true
product_tag = false
product_id_card = false
product_id_issuer = false
}
}
}
}

View file

@ -0,0 +1,138 @@
package com.tangem.devkit.ucase.variants.personalize.dto
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.tangem.commands.EllipticCurve
import com.tangem.commands.Product
import com.tangem.commands.ProductMaskBuilder
import com.tangem.commands.SigningMethodMask
import com.tangem.commands.personalization.entities.CardConfig
import com.tangem.commands.personalization.entities.NdefRecord
import java.util.*
class PersonalizationJson {
var issuerName = ""
var series = ""
var startNumber = 0L
var count = 0L
var PIN = ""
var PIN2 = ""
var PIN3 = ""
var hexCrExKey = ""
var CVC = ""
var pauseBeforePIN2 = 0L
var smartSecurityDelay = false
var curveID = ""
var SigningMethod = 0L
var MaxSignatures = 0L
var isReusable = false
var allowSwapPIN = false
var allowSwapPIN2 = false
var useActivation = false
var useCVC = false
var useNDEF = false
var useDynamicNDEF = false
var useOneCommandAtTime = false
var useBlock = false
var allowSelectBlockchain = false
var forbidPurgeWallet = false
var protocolAllowUnencrypted = false
var protocolAllowStaticEncryption = false
var protectIssuerDataAgainstReplay = false
var forbidDefaultPIN = false
var disablePrecomputedNDEF = false
var skipSecurityDelayIfValidatedByIssuer = false
var skipCheckPIN2andCVCIfValidatedByIssuer = false
var skipSecurityDelayIfValidatedByLinkedTerminal = false
var restrictOverwriteIssuerDataEx = false
var requireTerminalTxSignature = false
var requireTerminalCertSignature = false
var checkPIN3onCard = false
var createWallet = 0L
var issuerData = null
var ndef = mutableListOf<NdefRecord>()
var cardData = CardData()
var releaseVersion = false
var numberFormat = ""
companion object {
const val CUSTOM = "--- CUSTOM ---"
fun getJsonConverter(): Gson {
val builder = GsonBuilder().setPrettyPrinting()
return builder.create()
}
}
}
fun PersonalizationJson.toCardConfig(): CardConfig {
val isNote = cardData.product_note
val isTag = cardData.product_tag
val isIdCard = cardData.product_id_card
val isIdIssuer = cardData.product_id_issuer
val productMaskBuilder = ProductMaskBuilder()
if (isNote) productMaskBuilder.add(Product.Note)
if (isTag) productMaskBuilder.add(Product.Tag)
if (isIdCard) productMaskBuilder.add(Product.IdCard)
if (isIdIssuer) productMaskBuilder.add(Product.IdIssuer)
val productMask = productMaskBuilder.build()
val sdkCardData = com.tangem.commands.CardData(
blockchainName = this.cardData.blockchain,
batchId = this.cardData.batch,
productMask = productMask,
tokenSymbol = this.cardData.token_symbol,
tokenContractAddress = this.cardData.token_contract_address,
tokenDecimal = this.cardData.token_decimal.toInt(),
issuerName = this.issuerName,
manufactureDateTime = Calendar.getInstance().time,
manufacturerSignature = null)
return CardConfig(
this.issuerName,
"Tangem Test",
this.series,
this.startNumber,
this.count.toInt(),
this.PIN,
this.PIN2,
this.PIN3,
this.hexCrExKey,
this.CVC,
this.pauseBeforePIN2.toInt(),
this.smartSecurityDelay,
EllipticCurve.byName(this.curveID) ?: EllipticCurve.Secp256k1,
SigningMethodMask(this.SigningMethod.toInt()),
this.MaxSignatures.toInt(),
this.isReusable,
this.allowSwapPIN,
this.allowSwapPIN2,
this.useActivation,
this.useCVC,
this.useNDEF,
this.useDynamicNDEF,
this.useOneCommandAtTime,
this.useBlock,
this.allowSelectBlockchain,
this.forbidPurgeWallet,
this.protocolAllowUnencrypted,
this.protocolAllowStaticEncryption,
this.protectIssuerDataAgainstReplay,
this.forbidDefaultPIN,
this.disablePrecomputedNDEF,
this.skipSecurityDelayIfValidatedByIssuer,
this.skipCheckPIN2andCVCIfValidatedByIssuer,
this.skipSecurityDelayIfValidatedByLinkedTerminal,
this.restrictOverwriteIssuerDataEx,
this.requireTerminalTxSignature,
this.requireTerminalCertSignature,
this.checkPIN3onCard,
this.createWallet != 0L,
sdkCardData,
this.ndef
)
}

View file

@ -24,6 +24,7 @@ import com.tangem.devkit._arch.widget.WidgetBuilder
import com.tangem.devkit.commons.DialogController
import com.tangem.devkit.commons.view.MultiActionView
import com.tangem.devkit.commons.view.ViewAction
import com.tangem.devkit.extensions.copyToClipboard
import com.tangem.devkit.extensions.view.beginDelayedTransition
import com.tangem.devkit.ucase.domain.paramsManager.ItemsManager
import com.tangem.devkit.ucase.domain.paramsManager.PayloadKey
@ -50,7 +51,12 @@ import ru.dev.gbixahue.eu4d.lib.android.global.threading.postWork
*/
class PersonalizationFragment : BaseCardActionFragment(), PersonalizationPresetView {
override val itemsManager: ItemsManager by lazy { PersonalizationItemsManager(PersonalizationConfigStore(requireContext())) }
private lateinit var personalizationItemsManager: PersonalizationItemsManager
override val itemsManager: ItemsManager by lazy {
personalizationItemsManager = PersonalizationItemsManager(PersonalizationConfigStore(requireContext()))
personalizationItemsManager
}
override fun getLayoutId(): Int = R.layout.fg_base_action_layout
@ -106,20 +112,47 @@ class PersonalizationFragment : BaseCardActionFragment(), PersonalizationPresetV
override fun widgetsWasCreated() {
super.widgetsWasCreated()
val btnContainer = contentContainer.inflate<ViewGroup>(R.layout.view_simple_button)
val btn = btnContainer.findViewById<Button>(R.id.button)
val footerContainer = contentContainer.inflate<ViewGroup>(R.layout.fg_personalization_footer)
val show = StringId("show")
val hide = StringId("hide")
val multiAction = MultiActionView(mutableListOf(
ViewAction(show, R.string.show_rare_fields) { actionVM.showFields(ActionType.Personalize) },
ViewAction(hide, R.string.hide_rare_fields) { actionVM.hideFields(ActionType.Personalize) }
), btn)
multiAction.afterAction = {
multiAction.state = if (it == show) hide else show
fun initShowHideBtn(parent: ViewGroup) {
val btn = parent.findViewById<Button>(R.id.btn_show_hide_fields)
val show = StringId("show")
val hide = StringId("hide")
val multiAction = MultiActionView(mutableListOf(
ViewAction(show, R.string.show_rare_fields) { actionVM.showFields(ActionType.Personalize) },
ViewAction(hide, R.string.hide_rare_fields) { actionVM.hideFields(ActionType.Personalize) }
), btn)
multiAction.afterAction = {
multiAction.state = if (it == show) hide else show
}
multiAction.performAction(hide)
}
multiAction.performAction(hide)
contentContainer.addView(btnContainer)
fun initImportExportJson(parent: ViewGroup) {
val tvJsonExport = parent.findViewById<EditText>(R.id.et_json_export)
val btnExportJson = parent.findViewById<Button>(R.id.btn_export_json)
tvJsonExport.setOnClickListener {
val jsonString = tvJsonExport.text
Log.w(this, jsonString)
requireContext().copyToClipboard(jsonString, "Exported Json")
}
btnExportJson.setOnClickListener {
tvJsonExport.setText(personalizationItemsManager.exportJsonConfig())
}
val tvJsonImport = parent.findViewById<EditText>(R.id.et_json_import)
val btnImportJson = parent.findViewById<Button>(R.id.btn_import_json)
btnImportJson.setOnClickListener {
personalizationItemsManager.importJsonConfig(tvJsonImport.text.toString().trim())
}
}
initShowHideBtn(footerContainer)
initImportExportJson(footerContainer)
contentContainer.addView(footerContainer)
}
override fun handleResponseCardData(card: Card) {

View file

@ -1,11 +1,9 @@
package com.tangem.devkit.ucase.variants.responses.ui.widget
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.view.ViewGroup
import com.tangem.devkit.R
import com.tangem.devkit._arch.structure.abstraction.Item
import com.tangem.devkit.extensions.copyToClipboard
import com.tangem.devkit.ucase.variants.personalize.ui.widgets.DescriptionWidget
import ru.dev.gbixahue.eu4d.lib.android._android.views.stringFrom
import ru.dev.gbixahue.eu4d.lib.android._android.views.toast
@ -19,12 +17,8 @@ abstract class ResponseWidget(parent: ViewGroup, item: Item) : DescriptionWidget
init {
view.setOnClickListener {
val data = stringOf(item.getData<Any?>())
val clipboard = view.context.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
?: return@setOnClickListener
val clipboardData = "${getName()} - $data"
val clip: ClipData = ClipData.newPlainText("FieldValue", clipboardData)
clipboard.setPrimaryClip(clip)
view.context.copyToClipboard(clipboardData, "FieldValue")
val copyMessage = view.stringFrom(R.string.copy_to_clipboard)
view.toast("$copyMessage\n$clipboardData")

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/personalization_footer_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/v_export_import_json"/>
<Button
android:id="@+id/btn_show_hide_fields"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/def_indent"
tools:text="Show/Hide fields" />
</LinearLayout>

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/exim_json_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/def_indent"
android:layout_marginEnd="@dimen/def_indent"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<EditText
android:id="@+id/et_json_import"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="@string/stub" />
<Button
android:id="@+id/btn_import_json"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Import json" />
<Button
android:id="@+id/btn_export_json"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Prepare json to export" />
<EditText
android:id="@+id/et_json_export"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="@string/stub" />
</LinearLayout>

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>