diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/Extension.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/Extension.kt new file mode 100644 index 0000000000..71924302a3 --- /dev/null +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/Extension.kt @@ -0,0 +1,26 @@ +package com.tangem.tangemtest._arch.structure.abstraction + +import com.tangem.tangemtest._arch.structure.Id + +/** +[REDACTED_AUTHOR] + */ +fun List.findDataItem(id: Id): BaseItem? { + var foundItem: BaseItem? = null + iterate { + if (it.id == id) { + foundItem = it as? BaseItem + return@iterate + } + } + return foundItem +} + +fun List.iterate(func: (Item) -> Unit) { + forEach { + when (it) { + is BaseItem<*> -> func(it) + is Block -> it.itemList.iterate(func) + } + } +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ModelConverter.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ModelConverter.kt new file mode 100644 index 0000000000..09823a8495 --- /dev/null +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ModelConverter.kt @@ -0,0 +1,15 @@ +package com.tangem.tangemtest._arch.structure.abstraction + +import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter + +/** +[REDACTED_AUTHOR] + */ +interface DefaultConverter { + fun convert(from: A, default: B): B +} + +interface ItemsToModel : DefaultConverter, M> +interface ModelToItems : Converter> + +interface ModelConverter : DefaultConverter, M>, Converter> \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ViewModel.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ViewModel.kt index 63a54281d5..86d1d1b345 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ViewModel.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ViewModel.kt @@ -61,6 +61,8 @@ open class BaseItemViewModel : ItemViewModel { } class ViewState { + var isHiddenField = false + var descriptionVisibility: Int = 0x00000008 set(value) { field = value diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/DepersonalizeAction.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/DepersonalizeAction.kt index 6a08e2e816..2433302a4b 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/DepersonalizeAction.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/DepersonalizeAction.kt @@ -2,8 +2,8 @@ package com.tangem.tangemtest.ucase.domain.actions import com.tangem.tangemtest._arch.structure.Id import com.tangem.tangemtest._arch.structure.PayloadHolder +import com.tangem.tangemtest._arch.structure.abstraction.findDataItem import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback -import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem import com.tangem.tangemtest.ucase.variants.TlvId /** diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt index d82d8c7ddf..8ef5e4c0cc 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt @@ -1,25 +1,65 @@ package com.tangem.tangemtest.ucase.domain.actions -import com.tangem.commands.personalization.entities.CardConfig import com.tangem.tangemtest._arch.structure.PayloadHolder +import com.tangem.tangemtest._arch.structure.abstraction.Item +import com.tangem.tangemtest._arch.structure.abstraction.findDataItem +import com.tangem.tangemtest._arch.structure.impl.EditTextItem +import com.tangem.tangemtest._arch.structure.impl.NumberItem import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey +import com.tangem.tangemtest.ucase.tunnel.ActionView +import com.tangem.tangemtest.ucase.tunnel.ItemError +import com.tangem.tangemtest.ucase.variants.personalize.CardNumber +import com.tangem.tangemtest.ucase.variants.personalize.converter.PersonalizeConfigConverter +import com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo.PersonalizeConfigToCardConfig import com.tangem.tangemtest.ucase.variants.personalize.dto.DefaultPersonalizeParams +import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig +import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf /** [REDACTED_AUTHOR] */ class PersonalizeAction : BaseAction() { override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) { - val cardConfig = attrs.payload.remove(PayloadKey.cardConfig) as? CardConfig - ?: throw IllegalArgumentException("CardConfig must be in the payloads of the ParamsManager") + val itemList = attrs.payload[PayloadKey.itemList] as? List ?: return + val actionView = attrs.payload[PayloadKey.actionView] as? ActionView ?: return + + if (!checkSeries(itemList)) { + actionView.showSnackbar(ItemError.BadSeries) + return + } + if (!checkNumber(itemList)) { + actionView.showSnackbar(ItemError.BadCardNumber) + return + } val issuer = DefaultPersonalizeParams.issuer() val acquirer = DefaultPersonalizeParams.acquirer() val manufacturer = DefaultPersonalizeParams.manufacturer() + val personalizeConfig = PersonalizeConfigConverter().convert(itemList, PersonalizeConfig()) + val cardConfig = PersonalizeConfigToCardConfig().convert(personalizeConfig) + attrs.cardManager.personalize(cardConfig, issuer, manufacturer, acquirer) { handleResult(payload, it, null, attrs, callback) } } + + private fun checkSeries(itemList: List): Boolean { + val seriesItem = itemList.findDataItem(CardNumber.Series) as? EditTextItem ?: return false + val data = seriesItem.getData() ?: return false + + seriesItem.setData(data.toUpperCase()) + return data.length == 2 || data.length == 4 + } + + private fun checkNumber(itemList: List): Boolean { + val seriesItem = itemList.findDataItem(CardNumber.Series) as? EditTextItem ?: return false + val numberItem = itemList.findDataItem(CardNumber.Number) as? NumberItem ?: return false + val seriesData = seriesItem.getData() ?: return false + val numberData = stringOf(numberItem.getData()) + + return if (seriesData.length == 2 && numberData.length > 13) false + else !(seriesData.length == 4 && numberData.length > 11) + } } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/SignAction.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/SignAction.kt index f191a4aa4a..18fef1d8c5 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/SignAction.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/SignAction.kt @@ -2,8 +2,8 @@ package com.tangem.tangemtest.ucase.domain.actions import com.tangem.tangemtest._arch.structure.Id import com.tangem.tangemtest._arch.structure.PayloadHolder +import com.tangem.tangemtest._arch.structure.abstraction.findDataItem import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback -import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem import com.tangem.tangemtest.ucase.variants.TlvId import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/ItemsManager.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/ItemsManager.kt index 6a37f00b34..f97013d6f8 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/ItemsManager.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/ItemsManager.kt @@ -4,7 +4,6 @@ import com.tangem.CardManager import com.tangem.tangemtest._arch.structure.Id import com.tangem.tangemtest._arch.structure.Payload import com.tangem.tangemtest._arch.structure.PayloadHolder -import com.tangem.tangemtest._arch.structure.abstraction.BaseItem import com.tangem.tangemtest._arch.structure.abstraction.Item import com.tangem.tangemtest.ucase.domain.paramsManager.triggers.changeConsequence.ItemsChangeConsequence import com.tangem.tasks.TaskEvent @@ -34,15 +33,6 @@ interface PayloadKey { val incomingJson: String = "incomingJson" val card = "card" val actionView = "actionView" + val itemList = "itemList" } -} - -fun List.findItem(id: Id): Item? { - return firstOrNull { it.id == id } -} - -fun List.findDataItem(id: Id): BaseItem? { - val item = firstOrNull { it.id == id } - return if (item is BaseItem<*>) item as BaseItem - else null } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/BaseItemsManager.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/BaseItemsManager.kt index aaf280dedb..c9016165ac 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/BaseItemsManager.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/BaseItemsManager.kt @@ -4,12 +4,12 @@ import com.tangem.CardManager import com.tangem.tangemtest._arch.structure.Id import com.tangem.tangemtest._arch.structure.Payload import com.tangem.tangemtest._arch.structure.abstraction.Item +import com.tangem.tangemtest._arch.structure.abstraction.findDataItem import com.tangem.tangemtest.ucase.domain.actions.Action import com.tangem.tangemtest.ucase.domain.actions.AttrForAction import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback import com.tangem.tangemtest.ucase.domain.paramsManager.AffectedItemsCallback import com.tangem.tangemtest.ucase.domain.paramsManager.ItemsManager -import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem import com.tangem.tangemtest.ucase.domain.paramsManager.triggers.changeConsequence.ItemsChangeConsequence /** diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/PersonalizeItemsManager.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/PersonalizeItemsManager.kt index 82b6724052..7f40ac54f5 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/PersonalizeItemsManager.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/PersonalizeItemsManager.kt @@ -2,18 +2,14 @@ package com.tangem.tangemtest.ucase.domain.paramsManager.managers import com.tangem.CardManager import com.tangem.tangemtest._arch.structure.abstraction.Item -import com.tangem.tangemtest._arch.structure.impl.EditTextItem import com.tangem.tangemtest.ucase.domain.actions.PersonalizeAction import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback -import com.tangem.tangemtest.ucase.variants.TlvId /** [REDACTED_AUTHOR] */ class PersonalizeItemsManager : BaseItemsManager(PersonalizeAction()) { - override fun createItemsList(): List { - return listOf(EditTextItem(TlvId.CardId)) - } + override fun createItemsList(): List = listOf() override fun invokeMainAction(cardManager: CardManager, callback: ActionCallback) { action.executeMainAction(this, getAttrsForAction(cardManager), callback) diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/afterAction/AfterScanModifier.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/afterAction/AfterScanModifier.kt index cef30ec7f8..b75c721424 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/afterAction/AfterScanModifier.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/afterAction/AfterScanModifier.kt @@ -4,8 +4,8 @@ import com.tangem.commands.Card import com.tangem.commands.CardStatus import com.tangem.tangemtest._arch.structure.PayloadHolder import com.tangem.tangemtest._arch.structure.abstraction.Item +import com.tangem.tangemtest._arch.structure.abstraction.findDataItem import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey -import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem import com.tangem.tangemtest.ucase.tunnel.ActionView import com.tangem.tangemtest.ucase.tunnel.CardError import com.tangem.tangemtest.ucase.variants.TlvId diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/changeConsequence/ParamChangeConsequence.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/changeConsequence/ParamChangeConsequence.kt index d7da0d3d1b..2957d43a45 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/changeConsequence/ParamChangeConsequence.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/changeConsequence/ParamChangeConsequence.kt @@ -6,8 +6,8 @@ import com.tangem.common.extensions.calculateSha256 import com.tangem.common.extensions.calculateSha512 import com.tangem.tangemtest._arch.structure.PayloadHolder import com.tangem.tangemtest._arch.structure.abstraction.Item +import com.tangem.tangemtest._arch.structure.abstraction.findDataItem import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey -import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem import com.tangem.tangemtest.ucase.tunnel.ActionView import com.tangem.tangemtest.ucase.variants.TlvId import ru.dev.gbixahue.eu4d.lib.android.global.threading.postUI diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/responses/GsonInitializer.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/responses/GsonInitializer.kt index 826eeae2eb..32c93a7ff8 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/responses/GsonInitializer.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/responses/GsonInitializer.kt @@ -7,6 +7,8 @@ import com.tangem.commands.SettingsMask import com.tangem.commands.SigningMethod import com.tangem.common.extensions.toHexString import java.lang.reflect.Type +import java.text.DateFormat +import java.util.* /** [REDACTED_AUTHOR] @@ -20,6 +22,7 @@ class GsonInitializer { registerTypeAdapter(SigningMethod::class.java, SigningMethodTypeAdapter()) registerTypeAdapter(SettingsMask::class.java, SettingsMaskTypeAdapter()) registerTypeAdapter(ProductMask::class.java, ProductMaskTypeAdapter()) + registerTypeAdapter(Date::class.java, DateTypeAdapter()) } builder.setPrettyPrinting() return builder.create() @@ -52,4 +55,11 @@ class SigningMethodTypeAdapter : JsonSerializer { override fun serialize(src: SigningMethod, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { return JsonPrimitive(src.rawValue.toString()) } +} + +class DateTypeAdapter: JsonSerializer { + override fun serialize(src: Date, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { + val formatter = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale("en_US")) + return JsonPrimitive(formatter.format(src).toString()) + } } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/resources/initializers/PersonalizeResources.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/resources/initializers/PersonalizeResources.kt index d1d91d121f..f5e5338d4d 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/resources/initializers/PersonalizeResources.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/resources/initializers/PersonalizeResources.kt @@ -43,6 +43,7 @@ class PersonalizeResources() { private fun initCardNumber(holder: TypedHolder) { holder.register(CardNumber.Series, Resources(R.string.pers_item_series, R.string.info_pers_item_series)) holder.register(CardNumber.Number, Resources(R.string.pers_item_number, R.string.info_pers_item_number)) + holder.register(CardNumber.BatchId, Resources(R.string.pers_item_batch_id, R.string.info_pers_item_batch_id)) } private fun initCommon(holder: TypedHolder) { @@ -110,7 +111,7 @@ class PersonalizeResources() { private fun initSettingsMaskProtocolEnc(holder: TypedHolder) { holder.register(SettingsMaskProtocolEnc.AllowUnencrypted, Resources(R.string.pers_item_allow_unencrypted, R.string.info_pers_item_allow_unencrypted)) - holder.register(SettingsMaskProtocolEnc.AlloFastEncryption, Resources(R.string.pers_item_allow_fast_encryption, R.string.info_pers_item_allow_fast_encryption)) + holder.register(SettingsMaskProtocolEnc.AllowStaticEncryption, Resources(R.string.pers_item_allow_fast_encryption, R.string.info_pers_item_allow_fast_encryption)) } private fun initSettingsMaskNde(holder: TypedHolder) { diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/tunnel/Errors.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/tunnel/Errors.kt index e10f81c669..7b7cb530f7 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/tunnel/Errors.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/tunnel/Errors.kt @@ -5,6 +5,13 @@ import com.tangem.tangemtest._arch.structure.Id /** [REDACTED_AUTHOR] */ -enum class CardError : Id { - NotPersonalized +interface Errors: Id + +enum class CardError : Errors { + NotPersonalized, +} + +enum class ItemError: Errors { + BadSeries, + BadCardNumber, } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/tunnel/ViewScreen.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/tunnel/ViewScreen.kt index d7c1df09f2..ec84ed97ba 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/tunnel/ViewScreen.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/tunnel/ViewScreen.kt @@ -6,6 +6,7 @@ interface ViewScreen interface SnackbarHolder { fun showSnackbar(message: String) + fun showSnackbar(id: Int) fun showSnackbar(id: Id) } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/BaseCardActionFragment.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/BaseCardActionFragment.kt index c4202bfa01..d44d2c998d 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/BaseCardActionFragment.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/BaseCardActionFragment.kt @@ -133,11 +133,15 @@ abstract class BaseCardActionFragment : Fragment(), LayoutHolder, ActionView { override fun showSnackbar(id: Id) { // MainResourceHolder.safeGet<>() when (id) { - CardError.NotPersonalized -> showSnackbar(requireContext().getString(R.string.card_error_not_personalized)) + CardError.NotPersonalized -> showSnackbar(R.string.card_error_not_personalized) else -> showSnackbar(requireContext().getString(R.string.unknown)) } } + override fun showSnackbar(id: Int) { + showSnackbar(requireContext().getString(id)) + } + override fun showSnackbar(message: String) { Snackbar.make(mainView, message, BaseTransientBottomBar.LENGTH_SHORT).show() } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/Ids.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/Ids.kt index 44860aff33..eb631b200f 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/Ids.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/Ids.kt @@ -27,6 +27,7 @@ enum class BlockId : PersonalizeId { enum class CardNumber : BlockItem { Series, Number, + BatchId, } enum class Common : BlockItem { @@ -94,7 +95,7 @@ enum class SettingsMask : BlockItem { enum class SettingsMaskProtocolEnc : BlockItem { AllowUnencrypted, - AlloFastEncryption + AllowStaticEncryption } enum class SettingsMaskNdef : BlockItem { diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/DefaultValues.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/DefaultValues.kt new file mode 100644 index 0000000000..5b60115730 --- /dev/null +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/DefaultValues.kt @@ -0,0 +1,135 @@ +package com.tangem.tangemtest.ucase.variants.personalize.converter + +import com.tangem.commands.EllipticCurve +import com.tangem.tangemtest._arch.structure.Id +import com.tangem.tangemtest._arch.structure.impl.KeyValue +import com.tangem.tangemtest.ucase.variants.personalize.* +import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig +import ru.dev.gbixahue.eu4d.lib.kotlin.common.BaseTypedHolder + +/** +[REDACTED_AUTHOR] + */ +class PersonalizeConfigValuesHolder : BaseTypedHolder() { + + // All registered association values can't be objects + fun init(default: PersonalizeConfig) { + register(CardNumber.Series, Value(default.series)) + register(CardNumber.Number, Value(default.startNumber)) + register(CardNumber.BatchId, Value(default.batchId)) + register(Common.Curve, Value(default.curveID, Helper.listOfCurves())) + register(Common.Blockchain, Value(default.blockchain, Helper.listOfBlockchain())) + register(Common.BlockchainCustom, Value("")) + register(Common.MaxSignatures, Value(default.MaxSignatures)) + register(Common.CreateWallet, Value(default.createWallet)) + register(SigningMethod.SignTx, Value(default.SigningMethod0)) + register(SigningMethod.SignTxRaw, Value(default.SigningMethod1)) + register(SigningMethod.SignValidatedTx, Value(default.SigningMethod2)) + register(SigningMethod.SignValidatedTxRaw, Value(default.SigningMethod3)) + register(SigningMethod.SignValidatedTxIssuer, Value(default.SigningMethod4)) + register(SigningMethod.SignValidatedTxRawIssuer, Value(default.SigningMethod5)) + register(SigningMethod.SignExternal, Value(default.SigningMethod6)) + register(SignHashExProp.PinLessFloorLimit, Value(default.pinLessFloorLimit)) + register(SignHashExProp.CryptoExKey, Value(default.hexCrExKey)) + register(SignHashExProp.RequireTerminalCertSig, Value(default.requireTerminalCertSignature)) + register(SignHashExProp.RequireTerminalTxSig, Value(default.requireTerminalTxSignature)) + register(SignHashExProp.CheckPin3, Value(default.checkPIN3onCard)) + register(Denomination.WriteOnPersonalize, Value(default.writeOnPersonalization)) + register(Denomination.Denomination, Value(default.denomination)) + register(Token.ItsToken, Value(default.itsToken)) + register(Token.Symbol, Value(default.symbol)) + register(Token.ContractAddress, Value(default.contractAddress)) + register(Token.Decimal, Value(default.decimal)) + register(ProductMask.Note, Value(default.cardData.product_note)) + register(ProductMask.Tag, Value(default.cardData.product_tag)) + register(ProductMask.CardId, Value(default.cardData.product_id_card)) + register(SettingsMask.IsReusable, Value(default.isReusable)) + register(SettingsMask.NeedActivation, Value(default.useActivation)) + register(SettingsMask.ForbidPurge, Value(default.forbidPurgeWallet)) + register(SettingsMask.AllowSelectBlockchain, Value(default.allowSelectBlockchain)) + register(SettingsMask.UseBlock, Value(default.useBlock)) + register(SettingsMask.OneApdu, Value(default.oneApdu)) + register(SettingsMask.UseCvc, Value(default.useCVC)) + register(SettingsMask.AllowSwapPin, Value(default.allowSwapPIN)) + register(SettingsMask.AllowSwapPin2, Value(default.allowSwapPIN2)) + register(SettingsMask.ForbidDefaultPin, Value(default.forbidDefaultPIN)) + register(SettingsMask.SmartSecurityDelay, Value(default.smartSecurityDelay)) + register(SettingsMask.ProtectIssuerDataAgainstReplay, Value(default.protectIssuerDataAgainstReplay)) + register(SettingsMask.SkipSecurityDelayIfValidated, Value(default.skipSecurityDelayIfValidatedByIssuer)) + register(SettingsMask.SkipPin2CvcIfValidated, Value(default.skipCheckPIN2andCVCIfValidatedByIssuer)) + register(SettingsMask.SkipSecurityDelayOnLinkedTerminal, Value(default.skipSecurityDelayIfValidatedByLinkedTerminal)) + register(SettingsMask.RestrictOverwriteExtraIssuerData, Value(default.restrictOverwriteIssuerDataEx)) + register(SettingsMaskProtocolEnc.AllowUnencrypted, Value(default.protocolAllowUnencrypted)) + register(SettingsMaskProtocolEnc.AllowStaticEncryption, Value(default.protocolAllowStaticEncryption)) + register(SettingsMaskNdef.UseNdef, Value(default.useNDEF)) + register(SettingsMaskNdef.DynamicNdef, Value(default.useDynamicNDEF)) + register(SettingsMaskNdef.DisablePrecomputedNdef, Value(default.disablePrecomputedNDEF)) + register(SettingsMaskNdef.Aar, Value(default.aar, Helper.aarList())) + register(SettingsMaskNdef.AarCustom, Value(default.aar)) + register(Pins.Pin, Value(default.PIN)) + register(Pins.Pin2, Value(default.PIN2)) + register(Pins.Pin3, Value(default.PIN3)) + register(Pins.Cvc, Value(default.CVC)) + register(Pins.PauseBeforePin2, Value(default.pauseBeforePIN2, Helper.pauseBeforePin())) + } +} + +class Value( + private var value: Any? = null, + val list: List? = mutableListOf() +) { + fun get(): Any? = value + fun set(newValue: Any?) { + value = newValue + } +} + +internal class Helper { + companion object { + fun listOfCurves(): List { + return EllipticCurve.values().map { KeyValue(it.name, it.curve) } + } + + fun listOfBlockchain(): List { + return mutableListOf( + KeyValue("--- CUSTOM ---", ""), + KeyValue("BTC", "BTC"), + KeyValue("BTC/test", "BTC/test"), + KeyValue("ETH", "ETH"), + KeyValue("ETH/test", "ETH/test"), + KeyValue("BCH", "BCH"), + KeyValue("BCH/test", "BCH/test"), + KeyValue("LTC", "LTC"), + KeyValue("XLM", "XLM"), + KeyValue("XLM/test", "XLM/test"), + KeyValue("RSK", "RSK"), + KeyValue("XPR", "XPR"), + KeyValue("CARDANO", "CARDANO"), + KeyValue("BNB", "BNB"), + KeyValue("XTZ", "XTZ"), + KeyValue("DUC", "DUC") + ) + } + + fun aarList(): List { + return mutableListOf( + KeyValue("--- CUSTOM ---", ""), + KeyValue("Release APP", "com.tangem.wallet"), + KeyValue("Debug APP", "com.tangem.wallet.debug"), + KeyValue("None", "") + ) + } + + fun pauseBeforePin(): List { + return mutableListOf( + KeyValue("immediately", 0L), + KeyValue("2 seconds", 2000L), + KeyValue("5 seconds", 5000L), + KeyValue("15 seconds", 15000L), + KeyValue("30 seconds", 30000L), + KeyValue("1 minute", 60000L), + KeyValue("2 minute", 120000L) + ) + } + } +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/IdToValueAssociations.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/IdToValueAssociations.kt deleted file mode 100644 index 537f8a2b6f..0000000000 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/IdToValueAssociations.kt +++ /dev/null @@ -1,131 +0,0 @@ -package com.tangem.tangemtest.ucase.variants.personalize.converter - -import com.tangem.commands.EllipticCurve -import com.tangem.tangemtest._arch.structure.Id -import com.tangem.tangemtest._arch.structure.impl.KeyValue -import com.tangem.tangemtest.ucase.variants.personalize.* -import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig -import ru.dev.gbixahue.eu4d.lib.kotlin.common.BaseTypedHolder - -/** -[REDACTED_AUTHOR] - */ -class Value( - private var value: Any? = null, - val list: List? = mutableListOf() -) { - fun get(): Any? = value - fun set(newValue: Any?) { - value = newValue - } -} - -class IdToValueAssociations : BaseTypedHolder() { - - // All registered association values can't be objects - fun init(from: PersonalizeConfig) { - register(CardNumber.Series, Value(from.series)) - register(CardNumber.Number, Value(from.startNumber)) - register(Common.Curve, Value(from.curveID, Helper.listOfCurves())) - register(Common.Blockchain, Value(from.blockchain, Helper.listOfBlockchain())) - register(Common.BlockchainCustom, Value("")) - register(Common.MaxSignatures, Value(from.MaxSignatures)) - register(Common.CreateWallet, Value(from.createWallet)) - register(SigningMethod.SignTx, Value(from.SigningMethod0)) - register(SigningMethod.SignTxRaw, Value(from.SigningMethod1)) - register(SigningMethod.SignValidatedTx, Value(from.SigningMethod2)) - register(SigningMethod.SignValidatedTxRaw, Value(from.SigningMethod3)) - register(SigningMethod.SignValidatedTxIssuer, Value(from.SigningMethod4)) - register(SigningMethod.SignValidatedTxRawIssuer, Value(from.SigningMethod5)) - register(SigningMethod.SignExternal, Value(from.SigningMethod6)) - register(SignHashExProp.PinLessFloorLimit, Value(from.pinLessFloorLimit)) - register(SignHashExProp.CryptoExKey, Value(from.hexCrExKey)) - register(SignHashExProp.RequireTerminalCertSig, Value(from.requireTerminalCertSignature)) - register(SignHashExProp.RequireTerminalTxSig, Value(from.requireTerminalTxSignature)) - register(SignHashExProp.CheckPin3, Value(from.checkPIN3onCard)) - register(Denomination.WriteOnPersonalize, Value(from.writeOnPersonalization)) - register(Denomination.Denomination, Value(from.denomination)) - register(Token.ItsToken, Value(from.itsToken)) - register(Token.Symbol, Value(from.symbol)) - register(Token.ContractAddress, Value(from.contractAddress)) - register(Token.Decimal, Value(from.decimal)) - register(ProductMask.Note, Value(from.cardData.product_note)) - register(ProductMask.Tag, Value(from.cardData.product_tag)) - register(ProductMask.CardId, Value(from.cardData.product_id_card)) - register(SettingsMask.IsReusable, Value(from.isReusable)) - register(SettingsMask.NeedActivation, Value(from.useActivation)) - register(SettingsMask.ForbidPurge, Value(from.forbidPurgeWallet)) - register(SettingsMask.AllowSelectBlockchain, Value(from.allowSelectBlockchain)) - register(SettingsMask.UseBlock, Value(from.useBlock)) - register(SettingsMask.OneApdu, Value(from.oneApdu)) - register(SettingsMask.UseCvc, Value(from.useCVC)) - register(SettingsMask.AllowSwapPin, Value(from.allowSwapPIN)) - register(SettingsMask.AllowSwapPin2, Value(from.allowSwapPIN2)) - register(SettingsMask.ForbidDefaultPin, Value(from.forbidDefaultPIN)) - register(SettingsMask.SmartSecurityDelay, Value(from.smartSecurityDelay)) - register(SettingsMask.ProtectIssuerDataAgainstReplay, Value(from.protectIssuerDataAgainstReplay)) - register(SettingsMask.SkipSecurityDelayIfValidated, Value(from.skipSecurityDelayIfValidatedByIssuer)) - register(SettingsMask.SkipPin2CvcIfValidated, Value(from.skipCheckPIN2andCVCIfValidatedByIssuer)) - register(SettingsMask.SkipSecurityDelayOnLinkedTerminal, Value(from.skipSecurityDelayIfValidatedByLinkedTerminal)) - register(SettingsMask.RestrictOverwriteExtraIssuerData, Value(from.restrictOverwriteIssuerDataEx)) - register(SettingsMaskProtocolEnc.AllowUnencrypted, Value(from.protocolAllowUnencrypted)) - register(SettingsMaskProtocolEnc.AlloFastEncryption, Value(false)) - register(SettingsMaskNdef.UseNdef, Value(from.useNDEF)) - register(SettingsMaskNdef.DynamicNdef, Value(from.useDynamicNDEF)) - register(SettingsMaskNdef.DisablePrecomputedNdef, Value(from.disablePrecomputedNDEF)) - register(SettingsMaskNdef.Aar, Value(from.aar, Helper.aarList())) - register(SettingsMaskNdef.AarCustom, Value(from.aar)) - register(Pins.Pin, Value(from.PIN)) - register(Pins.Pin2, Value(from.PIN2)) - register(Pins.Pin3, Value(from.PIN3)) - register(Pins.Cvc, Value(from.CVC)) - register(Pins.PauseBeforePin2, Value(from.pauseBeforePIN2, Helper.pauseBeforePin())) - } -} - -internal class Helper { - companion object { - fun listOfCurves(): List { - return EllipticCurve.values().map { KeyValue(it.name, it.curve) } - } - - fun listOfBlockchain(): List { - return mutableListOf( - KeyValue("--- CUSTOM ---", "BTC/test"), - KeyValue("BTC", "BTC"), - KeyValue("BTC/test", "BTC/test"), - KeyValue("ETH", "ETH"), - KeyValue("ETH/test", "ETH/test"), - KeyValue("BCH", "BCH"), - KeyValue("BCH/test", "BCH/test"), - KeyValue("LTC", "LTC"), - KeyValue("XLM", "XLM"), - KeyValue("XLM/test", "XLM/test"), - KeyValue("RSK", "RSK"), - KeyValue("XPR", "XPR"), - KeyValue("CARDANO", "CARDANO") - ) - } - - fun aarList(): List { - return mutableListOf( - KeyValue("--- CUSTOM ---", ""), - KeyValue("Release APP", "com.tangem.wallet"), - KeyValue("Debug APP", "com.tangem.wallet.debug"), - KeyValue("None", "") - ) - } - - fun pauseBeforePin(): List { - return mutableListOf( - KeyValue("immediately", 0L), - KeyValue("2 seconds", 2000L), - KeyValue("5 seconds", 5000L), - KeyValue("15 seconds", 15000L), - KeyValue("30 seconds", 30000L), - KeyValue("1 minute", 60000L), - KeyValue("2 minute", 120000L) - ) - } - } -} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizeConfigConverter.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizeConfigConverter.kt index e4bee5910d..6b9b041b49 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizeConfigConverter.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizeConfigConverter.kt @@ -1,335 +1,26 @@ package com.tangem.tangemtest.ucase.variants.personalize.converter -import com.tangem.commands.CardData -import com.tangem.commands.EllipticCurve -import com.tangem.commands.ProductMaskBuilder -import com.tangem.commands.personalization.entities.CardConfig -import com.tangem.commands.personalization.entities.NdefRecord -import com.tangem.tangemtest._arch.structure.Additional -import com.tangem.tangemtest._arch.structure.Id -import com.tangem.tangemtest._arch.structure.abstraction.Block -import com.tangem.tangemtest._arch.structure.abstraction.ListItemBlock -import com.tangem.tangemtest._arch.structure.impl.* -import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey -import com.tangem.tangemtest.ucase.variants.personalize.* +import com.tangem.tangemtest._arch.structure.abstraction.Item +import com.tangem.tangemtest._arch.structure.abstraction.ItemsToModel +import com.tangem.tangemtest._arch.structure.abstraction.ModelConverter +import com.tangem.tangemtest._arch.structure.abstraction.ModelToItems +import com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo.ItemsToPersonalizeConfig +import com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo.PersonalizeConfigToItem import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig -import java.util.* /** [REDACTED_AUTHOR] */ -class PersonalizeConfigConverter { +class PersonalizeConfigConverter : ModelConverter { - private val associations: IdToValueAssociations = IdToValueAssociations() - private val valueMapper = ValueMapper() + private val toModel: ItemsToModel = ItemsToPersonalizeConfig() + private val toItems: ModelToItems = PersonalizeConfigToItem() - fun toBlock(from: PersonalizeConfig): List { - associations.init(from) - val blocList = mutableListOf() - 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()) - val payloadBlock = ListItemBlock(Additional.JSON_TAILS) - addPayload(payloadBlock, from) - blocList.add(payloadBlock) - return blocList + override fun convert(from: List, default: PersonalizeConfig): PersonalizeConfig { + return toModel.convert(from, default) } - private fun cardNumber(): Block { - val block = createBlock(BlockId.CardNumber) - mutableListOf( - CardNumber.Series, - CardNumber.Number - ).forEach { createItem(block, it as Id) } - return block + override fun convert(from: PersonalizeConfig): List { + return toItems.convert(from) } - - private fun common(): Block { - val block = createBlock(BlockId.Common) - mutableListOf( - Common.Curve, - Common.Blockchain, - Common.BlockchainCustom, - Common.MaxSignatures, - Common.CreateWallet - ).forEach { createItem(block, it) } - return block - } - - private fun signingMethod(): Block { - val block = createBlock(BlockId.SigningMethod) - mutableListOf( - SigningMethod.SignTx, - SigningMethod.SignTxRaw, - SigningMethod.SignValidatedTx, - SigningMethod.SignValidatedTxRaw, - SigningMethod.SignValidatedTxIssuer, - SigningMethod.SignValidatedTxRawIssuer, - SigningMethod.SignExternal - ).forEach { createItem(block, it) } - return block - } - - private fun signHashExProperties(): Block { - val block = createBlock(BlockId.SignHashExProp) - mutableListOf( - SignHashExProp.PinLessFloorLimit, - SignHashExProp.CryptoExKey, - SignHashExProp.RequireTerminalCertSig, - SignHashExProp.RequireTerminalTxSig, - SignHashExProp.CheckPin3 - ).forEach { createItem(block, it) } - return block - } - - private fun denomination(): Block { - val block = createBlock(BlockId.Denomination) - mutableListOf( - Denomination.WriteOnPersonalize, - Denomination.Denomination - ).forEach { createItem(block, it) } - return block - } - - private fun token(): Block { - val block = createBlock(BlockId.Token) - mutableListOf( - Token.ItsToken, - Token.Symbol, - Token.ContractAddress, - Token.Decimal - ).forEach { createItem(block, it) } - return block - } - - private fun productMask(): Block { - val block = createBlock(BlockId.ProdMask) - mutableListOf( - ProductMask.Note, - ProductMask.Tag, - ProductMask.CardId - ).forEach { createItem(block, it) } - return block - } - - private fun settingsMask(): Block { - val block = createBlock(BlockId.SettingsMask) - mutableListOf( - SettingsMask.IsReusable, - SettingsMask.NeedActivation, - SettingsMask.ForbidPurge, - SettingsMask.AllowSelectBlockchain, - SettingsMask.UseBlock, - SettingsMask.OneApdu, - SettingsMask.UseCvc, - SettingsMask.AllowSwapPin, - SettingsMask.AllowSwapPin2, - SettingsMask.ForbidDefaultPin, - SettingsMask.SmartSecurityDelay, - SettingsMask.ProtectIssuerDataAgainstReplay, - SettingsMask.SkipSecurityDelayIfValidated, - SettingsMask.SkipPin2CvcIfValidated, - SettingsMask.SkipSecurityDelayOnLinkedTerminal, - SettingsMask.RestrictOverwriteExtraIssuerData - ).forEach { createItem(block, it) } - return block - } - - private fun settingsMaskProtocolEnc(): Block { - val block = createBlock(BlockId.SettingsMaskProtocolEnc) - mutableListOf( - SettingsMaskProtocolEnc.AllowUnencrypted, - SettingsMaskProtocolEnc.AlloFastEncryption).forEach { createItem(block, it) } - return block - } - - private fun settingsMaskNdef(): Block { - val block = createBlock(BlockId.SettingsMaskNdef) - mutableListOf( - SettingsMaskNdef.UseNdef, - SettingsMaskNdef.DynamicNdef, - SettingsMaskNdef.DisablePrecomputedNdef, - SettingsMaskNdef.Aar, - SettingsMaskNdef.AarCustom - ).forEach { createItem(block, it) } - return block - } - - private fun pins(): Block { - val block = createBlock(BlockId.Pins) - mutableListOf(Pins.Pin, Pins.Pin2, Pins.Pin3, Pins.Cvc, Pins.PauseBeforePin2) - .forEach { createItem(block, it) } - return block - } - - private fun createBlock(id: Id): ListItemBlock { - return ListItemBlock(id).apply { addItem(TextItem(id)) } - } - - private fun addPayload(block: Block, from: PersonalizeConfig) { - block.payload[PayloadKey.incomingJson] = from - } - - private fun createItem(block: ListItemBlock, id: Id) { - val holder = associations.get(id) ?: return - val item = when { - IdItemHelper.blockIdList.contains(id) -> TextItem(id, holder.get() as? String) - IdItemHelper.listItemList.contains(id) -> ListItem(id, holder.list as List, holder.get()) - IdItemHelper.boolList.contains(id) -> BoolItem(id, holder.get() as? Boolean) - IdItemHelper.editTextList.contains(id) -> EditTextItem(id, holder.get() as? String) - IdItemHelper.numberList.contains(id) -> NumberItem(id, holder.get() as? Number) - else -> ListItemBlock(Additional.UNDEFINED) - } - block.addItem(item) - } - - fun toConfig(blockList: List, defaultConfig: PersonalizeConfig): PersonalizeConfig { - return valueMapper.mapOnObject(blockList, defaultConfig) - } - - fun createCardConfig(applyConfig: PersonalizeConfig): CardConfig { - val signingMethod = com.tangem.commands.SigningMethod.build( - signHash = applyConfig.SigningMethod0, - signRaw = applyConfig.SigningMethod1, - signHashValidatedByIssuer = applyConfig.SigningMethod2, - signRawValidatedByIssuer = applyConfig.SigningMethod3, - signHashValidatedByIssuerAndWriteIssuerData = applyConfig.SigningMethod4, - signRawValidatedByIssuerAndWriteIssuerData = applyConfig.SigningMethod5, - signPos = applyConfig.SigningMethod6 - ) - - val isNote = applyConfig.cardData.product_note - val isTag = applyConfig.cardData.product_tag - val isIdCard = applyConfig.cardData.product_id_card - - val productMaskBuilder = ProductMaskBuilder() - if (isNote) productMaskBuilder.add(com.tangem.commands.ProductMask.note) - if (isTag) productMaskBuilder.add(com.tangem.commands.ProductMask.tag) - if (isIdCard) productMaskBuilder.add(com.tangem.commands.ProductMask.idCard) - val productMask = productMaskBuilder.build() - - var tokenSymbol: String? = null - var tokenContractAddress: String? = null - var tokenDecimal: Int? = null - if (applyConfig.itsToken) { - tokenSymbol = applyConfig.symbol - tokenContractAddress = applyConfig.contractAddress - tokenDecimal = applyConfig.decimal.toInt() - } - - val cardData = CardData( - blockchainName = applyConfig.blockchain, - batchId = applyConfig.cardData.batch, - productMask = productMask, - tokenSymbol = tokenSymbol, - tokenContractAddress = tokenContractAddress, - tokenDecimal = tokenDecimal, - issuerName = null, - manufactureDateTime = Calendar.getInstance().time, - manufacturerSignature = null) - - - val ndefs = mutableListOf() - when (applyConfig.aar) { - "None" -> null - "--- CUSTOM ---" -> NdefRecord(NdefRecord.Type.AAR, applyConfig.aarCustom) - else -> NdefRecord(NdefRecord.Type.AAR, applyConfig.aar) - }?.let { ndefs.add(it) } - - return CardConfig( - "Tangem", - "Tangem Test", - applyConfig.series, - applyConfig.startNumber, - 1000, - applyConfig.PIN, - applyConfig.PIN2, - applyConfig.PIN3, - applyConfig.hexCrExKey, - applyConfig.CVC, - applyConfig.pauseBeforePIN2.toInt(), - applyConfig.smartSecurityDelay, - EllipticCurve.byName(applyConfig.curveID) ?: EllipticCurve.Secp256k1, - signingMethod, - applyConfig.MaxSignatures.toInt(), - applyConfig.isReusable, - applyConfig.allowSwapPIN, - applyConfig.allowSwapPIN2, - applyConfig.useActivation, - applyConfig.useCVC, - applyConfig.useNDEF, - applyConfig.useDynamicNDEF, - applyConfig.oneApdu, - applyConfig.useBlock, - applyConfig.allowSelectBlockchain, - applyConfig.forbidPurgeWallet, - applyConfig.protocolAllowUnencrypted, - applyConfig.protocolAllowStaticEncryption, - applyConfig.protectIssuerDataAgainstReplay, - applyConfig.forbidDefaultPIN, - applyConfig.disablePrecomputedNDEF, - applyConfig.skipSecurityDelayIfValidatedByIssuer, - applyConfig.skipCheckPIN2andCVCIfValidatedByIssuer, - applyConfig.skipSecurityDelayIfValidatedByLinkedTerminal, - applyConfig.restrictOverwriteIssuerDataEx, - applyConfig.requireTerminalTxSignature, - applyConfig.requireTerminalCertSignature, - applyConfig.checkPIN3onCard, - applyConfig.createWallet, - cardData, - ndefs - ) - } -} - -class IdItemHelper { - companion object { - val blockIdList = mutableListOf( - BlockId.CardNumber, BlockId.Common, BlockId.SigningMethod, BlockId.SignHashExProp, BlockId.Denomination, - BlockId.Token, BlockId.ProdMask, BlockId.SettingsMask, BlockId.SettingsMaskProtocolEnc, - BlockId.SettingsMaskNdef, BlockId.Pins - ) - - val listItemList = mutableListOf(Common.Curve, Common.Blockchain, SettingsMaskNdef.Aar, Pins.PauseBeforePin2) - - val boolList = mutableListOf( - Common.CreateWallet, SigningMethod.SignTx, SigningMethod.SignTxRaw, SigningMethod.SignValidatedTx, - SigningMethod.SignValidatedTxRaw, SigningMethod.SignValidatedTxIssuer, - SigningMethod.SignValidatedTxRawIssuer, SigningMethod.SignExternal, SignHashExProp.RequireTerminalCertSig, - SignHashExProp.RequireTerminalTxSig, SignHashExProp.CheckPin3, Denomination.WriteOnPersonalize, Token.ItsToken, - ProductMask.Note, ProductMask.Tag, ProductMask.CardId, SettingsMask.IsReusable, SettingsMask.NeedActivation, - SettingsMask.ForbidPurge, SettingsMask.AllowSelectBlockchain, SettingsMask.UseBlock, SettingsMask.OneApdu, - SettingsMask.UseCvc, SettingsMask.AllowSwapPin, SettingsMask.AllowSwapPin2, SettingsMask.ForbidDefaultPin, - SettingsMask.SmartSecurityDelay, SettingsMask.ProtectIssuerDataAgainstReplay, - SettingsMask.SkipSecurityDelayIfValidated, SettingsMask.SkipPin2CvcIfValidated, - SettingsMask.SkipSecurityDelayOnLinkedTerminal, SettingsMask.RestrictOverwriteExtraIssuerData, - SettingsMaskProtocolEnc.AllowUnencrypted, SettingsMaskProtocolEnc.AlloFastEncryption, - SettingsMaskNdef.UseNdef, SettingsMaskNdef.DynamicNdef, SettingsMaskNdef.DisablePrecomputedNdef - ) - - val editTextList = mutableListOf( - CardNumber.Series, Common.BlockchainCustom, SignHashExProp.CryptoExKey, Token.Symbol, - Token.ContractAddress, Pins.Pin, Pins.Pin2, Pins.Pin3, Pins.Cvc, SettingsMaskNdef.AarCustom - ) - - val numberList = mutableListOf( - CardNumber.Number, Common.MaxSignatures, SignHashExProp.PinLessFloorLimit, Denomination.Denomination, Token.Decimal - ) - } -} - -class JsonTails( - val count: Int, - val numberFormat: String, - val issuerData: Any?, - val releaseVersion: Boolean, - val issuerName: String -) \ No newline at end of file +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/fromTo/ItemTypes.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/fromTo/ItemTypes.kt new file mode 100644 index 0000000000..7deee294d8 --- /dev/null +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/fromTo/ItemTypes.kt @@ -0,0 +1,46 @@ +package com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo + +import com.tangem.tangemtest.ucase.variants.personalize.* + +class ItemTypes { + + val blockIdList = mutableListOf( + BlockId.CardNumber, BlockId.Common, BlockId.SigningMethod, BlockId.SignHashExProp, BlockId.Denomination, + BlockId.Token, BlockId.ProdMask, BlockId.SettingsMask, BlockId.SettingsMaskProtocolEnc, + BlockId.SettingsMaskNdef, BlockId.Pins + ) + + val listItemList = mutableListOf(Common.Curve, Common.Blockchain, SettingsMaskNdef.Aar, Pins.PauseBeforePin2) + + val boolList = mutableListOf( + Common.CreateWallet, SigningMethod.SignTx, SigningMethod.SignTxRaw, SigningMethod.SignValidatedTx, + SigningMethod.SignValidatedTxRaw, SigningMethod.SignValidatedTxIssuer, + SigningMethod.SignValidatedTxRawIssuer, SigningMethod.SignExternal, SignHashExProp.RequireTerminalCertSig, + SignHashExProp.RequireTerminalTxSig, SignHashExProp.CheckPin3, Denomination.WriteOnPersonalize, Token.ItsToken, + ProductMask.Note, ProductMask.Tag, ProductMask.CardId, SettingsMask.IsReusable, SettingsMask.NeedActivation, + SettingsMask.ForbidPurge, SettingsMask.AllowSelectBlockchain, SettingsMask.UseBlock, SettingsMask.OneApdu, + SettingsMask.UseCvc, SettingsMask.AllowSwapPin, SettingsMask.AllowSwapPin2, SettingsMask.ForbidDefaultPin, + SettingsMask.SmartSecurityDelay, SettingsMask.ProtectIssuerDataAgainstReplay, + SettingsMask.SkipSecurityDelayIfValidated, SettingsMask.SkipPin2CvcIfValidated, + SettingsMask.SkipSecurityDelayOnLinkedTerminal, SettingsMask.RestrictOverwriteExtraIssuerData, + SettingsMaskProtocolEnc.AllowUnencrypted, SettingsMaskProtocolEnc.AllowStaticEncryption, + SettingsMaskNdef.UseNdef, SettingsMaskNdef.DynamicNdef, SettingsMaskNdef.DisablePrecomputedNdef + ) + + val editTextList = mutableListOf( + CardNumber.Series, CardNumber.BatchId, Common.BlockchainCustom, SignHashExProp.CryptoExKey, Token.Symbol, + Token.ContractAddress, Pins.Pin, Pins.Pin2, Pins.Pin3, Pins.Cvc, SettingsMaskNdef.AarCustom + ) + + val numberList = mutableListOf( + CardNumber.Number, Common.MaxSignatures, SignHashExProp.PinLessFloorLimit, Denomination.Denomination, Token.Decimal + ) + + val hiddenList = mutableListOf( + CardNumber.Series, CardNumber.BatchId, Pins.Pin3, SigningMethod.SignExternal, + SignHashExProp.CryptoExKey, SignHashExProp.CheckPin3, SettingsMask.OneApdu, + SettingsMask.UseBlock, SettingsMask.ProtectIssuerDataAgainstReplay, + SignHashExProp.RequireTerminalCertSig, SignHashExProp.RequireTerminalTxSig + ) + +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/ValueMapper.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/fromTo/ItemsToPersonalizeConfig.kt similarity index 81% rename from tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/ValueMapper.kt rename to tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/fromTo/ItemsToPersonalizeConfig.kt index 9063a56fe3..f1a8d7a1ac 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/ValueMapper.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/fromTo/ItemsToPersonalizeConfig.kt @@ -1,45 +1,44 @@ -package com.tangem.tangemtest.ucase.variants.personalize.converter +package com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo import com.tangem.tangemtest._arch.structure.Id import com.tangem.tangemtest._arch.structure.abstraction.BaseItem import com.tangem.tangemtest._arch.structure.abstraction.Block import com.tangem.tangemtest._arch.structure.abstraction.Item +import com.tangem.tangemtest._arch.structure.abstraction.ItemsToModel import com.tangem.tangemtest._arch.structure.impl.KeyValue import com.tangem.tangemtest._arch.structure.impl.ListValueWrapper import com.tangem.tangemtest.ucase.variants.personalize.* +import com.tangem.tangemtest.ucase.variants.personalize.converter.PersonalizeConfigValuesHolder import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig import ru.dev.gbixahue.eu4d.lib.android.global.log.Log /** [REDACTED_AUTHOR] */ -class ValueMapper { - private val default: IdToValueAssociations = IdToValueAssociations() - private val updatedByItemList: IdToValueAssociations = IdToValueAssociations() +class ItemsToPersonalizeConfig : ItemsToModel { + protected val valuesHolder = PersonalizeConfigValuesHolder() - - fun mapOnObject(itemList: List, defaultConfig: PersonalizeConfig): PersonalizeConfig { - default.init(defaultConfig) - updatedByItemList.init(defaultConfig) - startMapping(itemList) - return createConfig() + override fun convert(from: List, default: PersonalizeConfig): PersonalizeConfig { + valuesHolder.init(default) + mapListItems(from) + return createModel() } - private fun startMapping(itemList: List) { - itemList.forEach { item -> mapItem(item) } + private fun mapListItems(itemList: List) { + itemList.forEach { item -> mapItemToHolder(item) } } - private fun mapItem(item: Item) { + private fun mapItemToHolder(item: Item) { when (item) { - is Block -> startMapping(item.itemList) + is Block -> mapListItems(item.itemList) is BaseItem<*> -> { - val value = updatedByItemList.get(item.id) ?: return - value.set(item.viewModel.data) + val defValue = valuesHolder.get(item.id) ?: return + defValue.set(item.viewModel.data) } } } - private fun createConfig(): PersonalizeConfig { + private fun createModel(): PersonalizeConfig { val export = PersonalizeConfig() export.series = getTyped(CardNumber.Series) export.startNumber = getTyped(CardNumber.Number) @@ -86,7 +85,7 @@ class ValueMapper { export.skipSecurityDelayIfValidatedByLinkedTerminal = getTyped(SettingsMask.SkipSecurityDelayOnLinkedTerminal) export.restrictOverwriteIssuerDataEx = getTyped(SettingsMask.RestrictOverwriteExtraIssuerData) export.protocolAllowUnencrypted = getTyped(SettingsMaskProtocolEnc.AllowUnencrypted) - export.allowFastEncryption = getTyped(SettingsMaskProtocolEnc.AlloFastEncryption) + export.protocolAllowStaticEncryption = getTyped(SettingsMaskProtocolEnc.AllowStaticEncryption) export.useNDEF = getTyped(SettingsMaskNdef.UseNdef) export.useDynamicNDEF = getTyped(SettingsMaskNdef.DynamicNdef) export.disablePrecomputedNDEF = getTyped(SettingsMaskNdef.DisablePrecomputedNdef) @@ -101,12 +100,12 @@ class ValueMapper { } private inline fun getTyped(id: Id): Type { - return getTypedBy(updatedByItemList, id) ?: getTypedBy(default, id)!! + return getTypedBy(valuesHolder, id)!! } - private inline fun getTypedBy(associations: IdToValueAssociations, id: Id): Type? { + private inline fun getTypedBy(holder: PersonalizeConfigValuesHolder, id: Id): Type? { Log.d(this, "getTyped for id: $id") - var typedValue = associations.get(id)?.get() + var typedValue = holder.get(id)?.get() typedValue = when (typedValue) { is ListValueWrapper -> (typedValue.selectedItem as KeyValue).value as Type diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/fromTo/PersonalizeConfigTo.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/fromTo/PersonalizeConfigTo.kt new file mode 100644 index 0000000000..a1186a3291 --- /dev/null +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/fromTo/PersonalizeConfigTo.kt @@ -0,0 +1,298 @@ +package com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo + +import com.tangem.commands.CardData +import com.tangem.commands.EllipticCurve +import com.tangem.commands.ProductMaskBuilder +import com.tangem.commands.personalization.entities.CardConfig +import com.tangem.commands.personalization.entities.NdefRecord +import com.tangem.tangemtest._arch.structure.Additional +import com.tangem.tangemtest._arch.structure.Id +import com.tangem.tangemtest._arch.structure.abstraction.* +import com.tangem.tangemtest._arch.structure.impl.* +import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey +import com.tangem.tangemtest.ucase.variants.personalize.* +import com.tangem.tangemtest.ucase.variants.personalize.converter.PersonalizeConfigValuesHolder +import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig +import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter +import java.util.* + +/** +[REDACTED_AUTHOR] + */ +class PersonalizeConfigToItem : ModelToItems { + private val valuesHolder = PersonalizeConfigValuesHolder() + private val itemTypes = ItemTypes() + + override fun convert(from: PersonalizeConfig): List { + valuesHolder.init(from) + val blocList = mutableListOf() + 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()) + val payloadBlock = ListItemBlock(Additional.JSON_TAILS) + addPayload(payloadBlock, from) + blocList.add(payloadBlock) + blocList.iterate { + if (itemTypes.hiddenList.contains(it.id)) { + (it as BaseItem<*>)?.viewModel.viewState.isHiddenField = true + } + } + return blocList + } + + private fun cardNumber(): Block { + val block = createBlock(BlockId.CardNumber) + mutableListOf( + CardNumber.Series, + CardNumber.Number, + CardNumber.BatchId + ).forEach { createItem(block, it as Id) } + return block + } + + private fun common(): Block { + val block = createBlock(BlockId.Common) + mutableListOf( + Common.Curve, + Common.Blockchain, + Common.BlockchainCustom, + Common.MaxSignatures, + Common.CreateWallet + ).forEach { createItem(block, it) } + return block + } + + private fun signingMethod(): Block { + val block = createBlock(BlockId.SigningMethod) + mutableListOf( + SigningMethod.SignTx, + SigningMethod.SignTxRaw, + SigningMethod.SignValidatedTx, + SigningMethod.SignValidatedTxRaw, + SigningMethod.SignValidatedTxIssuer, + SigningMethod.SignValidatedTxRawIssuer, + SigningMethod.SignExternal + ).forEach { createItem(block, it) } + return block + } + + private fun signHashExProperties(): Block { + val block = createBlock(BlockId.SignHashExProp) + mutableListOf( + SignHashExProp.PinLessFloorLimit, + SignHashExProp.CryptoExKey, + SignHashExProp.RequireTerminalCertSig, + SignHashExProp.RequireTerminalTxSig, + SignHashExProp.CheckPin3 + ).forEach { createItem(block, it) } + return block + } + + private fun denomination(): Block { + val block = createBlock(BlockId.Denomination) + mutableListOf( + Denomination.WriteOnPersonalize, + Denomination.Denomination + ).forEach { createItem(block, it) } + return block + } + + private fun token(): Block { + val block = createBlock(BlockId.Token) + mutableListOf( + Token.ItsToken, + Token.Symbol, + Token.ContractAddress, + Token.Decimal + ).forEach { createItem(block, it) } + return block + } + + private fun productMask(): Block { + val block = createBlock(BlockId.ProdMask) + mutableListOf( + ProductMask.Note, + ProductMask.Tag, + ProductMask.CardId + ).forEach { createItem(block, it) } + return block + } + + private fun settingsMask(): Block { + val block = createBlock(BlockId.SettingsMask) + mutableListOf( + SettingsMask.IsReusable, + SettingsMask.NeedActivation, + SettingsMask.ForbidPurge, + SettingsMask.AllowSelectBlockchain, + SettingsMask.UseBlock, + SettingsMask.OneApdu, + SettingsMask.UseCvc, + SettingsMask.AllowSwapPin, + SettingsMask.AllowSwapPin2, + SettingsMask.ForbidDefaultPin, + SettingsMask.SmartSecurityDelay, + SettingsMask.ProtectIssuerDataAgainstReplay, + SettingsMask.SkipSecurityDelayIfValidated, + SettingsMask.SkipPin2CvcIfValidated, + SettingsMask.SkipSecurityDelayOnLinkedTerminal, + SettingsMask.RestrictOverwriteExtraIssuerData + ).forEach { createItem(block, it) } + return block + } + + private fun settingsMaskProtocolEnc(): Block { + val block = createBlock(BlockId.SettingsMaskProtocolEnc) + mutableListOf( + SettingsMaskProtocolEnc.AllowUnencrypted, + SettingsMaskProtocolEnc.AllowStaticEncryption + ).forEach { createItem(block, it) } + return block + } + + private fun settingsMaskNdef(): Block { + val block = createBlock(BlockId.SettingsMaskNdef) + mutableListOf( + SettingsMaskNdef.UseNdef, + SettingsMaskNdef.DynamicNdef, + SettingsMaskNdef.DisablePrecomputedNdef, + SettingsMaskNdef.Aar, + SettingsMaskNdef.AarCustom + ).forEach { createItem(block, it) } + return block + } + + private fun pins(): Block { + val block = createBlock(BlockId.Pins) + mutableListOf(Pins.Pin, Pins.Pin2, Pins.Pin3, Pins.Cvc, Pins.PauseBeforePin2) + .forEach { createItem(block, it) } + return block + } + + private fun createBlock(id: Id): ListItemBlock { + return ListItemBlock(id).apply { addItem(TextItem(id)) } + } + + private fun addPayload(block: Block, from: PersonalizeConfig) { + block.payload[PayloadKey.incomingJson] = from + } + + private fun createItem(block: ListItemBlock, id: Id) { + val holder = valuesHolder.get(id) ?: return + val item = when { + itemTypes.blockIdList.contains(id) -> TextItem(id, holder.get() as? String) + itemTypes.listItemList.contains(id) -> ListItem(id, holder.list as List, holder.get()) + itemTypes.boolList.contains(id) -> BoolItem(id, holder.get() as? Boolean) + itemTypes.editTextList.contains(id) -> EditTextItem(id, holder.get() as? String) + itemTypes.numberList.contains(id) -> NumberItem(id, holder.get() as? Number) + else -> ListItemBlock(Additional.UNDEFINED) + } + block.addItem(item) + } +} + +class PersonalizeConfigToCardConfig : Converter { + + override fun convert(from: PersonalizeConfig): CardConfig { + val signingMethod = com.tangem.commands.SigningMethod.build( + signHash = from.SigningMethod0, + signRaw = from.SigningMethod1, + signHashValidatedByIssuer = from.SigningMethod2, + signRawValidatedByIssuer = from.SigningMethod3, + signHashValidatedByIssuerAndWriteIssuerData = from.SigningMethod4, + signRawValidatedByIssuerAndWriteIssuerData = from.SigningMethod5, + signPos = from.SigningMethod6 + ) + + val isNote = from.cardData.product_note + val isTag = from.cardData.product_tag + val isIdCard = from.cardData.product_id_card + + val productMaskBuilder = ProductMaskBuilder() + if (isNote) productMaskBuilder.add(com.tangem.commands.ProductMask.note) + if (isTag) productMaskBuilder.add(com.tangem.commands.ProductMask.tag) + if (isIdCard) productMaskBuilder.add(com.tangem.commands.ProductMask.idCard) + 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() + 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 + ) + } +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/PersonalizeConfig.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/PersonalizeConfig.kt index c3362c4971..1c16a6d5f0 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/PersonalizeConfig.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/PersonalizeConfig.kt @@ -8,11 +8,12 @@ class PersonalizeConfig { // Card number var series = "BB" var startNumber: Long = 300000000000 + var batchId = "ffff" // Common var curveID = "ed25519" - var blockchain = "BTC" + var blockchain = "BTC/test" var blockchainCustom = "" var MaxSignatures: Long = 100 var createWallet = false @@ -71,7 +72,6 @@ class PersonalizeConfig { // Settings mask - protocol encryption var protocolAllowUnencrypted = true - var allowFastEncryption = false var protocolAllowStaticEncryption = true diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeFragment.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeFragment.kt index f7c8ed9ea9..3456d91ad2 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeFragment.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeFragment.kt @@ -9,28 +9,32 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.Observer +import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.Snackbar import com.tangem.CardManager import com.tangem.tangem_sdk_new.extensions.init import com.tangem.tangemtest.R -import com.tangem.tangemtest._arch.structure.abstraction.Block +import com.tangem.tangemtest._arch.structure.Id +import com.tangem.tangemtest._arch.structure.abstraction.Item import com.tangem.tangemtest._main.MainViewModel import com.tangem.tangemtest.ucase.domain.paramsManager.ItemsManager import com.tangem.tangemtest.ucase.domain.paramsManager.ParamsManagerFactory import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey import com.tangem.tangemtest.ucase.resources.ActionType +import com.tangem.tangemtest.ucase.tunnel.ActionView +import com.tangem.tangemtest.ucase.tunnel.CardError +import com.tangem.tangemtest.ucase.tunnel.ItemError import com.tangem.tangemtest.ucase.ui.ActionViewModelFactory import com.tangem.tangemtest.ucase.ui.ParamsViewModel import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig import com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.WidgetBuilder -import kotlinx.android.synthetic.main.fg_personalize.* import ru.dev.gbixahue.eu4d.lib.android.global.log.Log /** [REDACTED_AUTHOR] */ -class PersonalizeFragment : Fragment() { +class PersonalizeFragment : Fragment(), ActionView { private val mainActivityVM: MainViewModel by activityViewModels() private val personalizeVM: PersonalizeViewModel by viewModels { PersonalizeViewModelFactory(PersonalizeConfig()) } @@ -38,10 +42,9 @@ class PersonalizeFragment : Fragment() { private val itemsManager: ItemsManager by lazy { ParamsManagerFactory.createFactory().get(ActionType.Personalize)!! } private val paramsVM: ParamsViewModel by viewModels() { ActionViewModelFactory(itemsManager) } - private val blockContainer: ViewGroup by lazy { - mainView.findViewById(R.id.ll_container) - } private lateinit var mainView: View + private val blockContainer: ViewGroup by lazy { mainView.findViewById(R.id.ll_container) } + private val actionFab: FloatingActionButton by lazy { mainView.findViewById(R.id.fab_action) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { Log.d(this, "onCreateView") @@ -52,11 +55,16 @@ class PersonalizeFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val blockList = mutableListOf() + val blockList = mutableListOf() personalizeVM.ldBlockList.observe(viewLifecycleOwner, Observer { list -> blockList.clear() blockList.addAll(list) blockList.forEach { WidgetBuilder().build(it, blockContainer) } + paramsVM.attachToPayload(mutableMapOf( + PayloadKey.actionView to this as ActionView, + PayloadKey.itemList to blockList + )) + }) mainActivityVM.ldDescriptionSwitch.observe(viewLifecycleOwner, Observer { personalizeVM.toggleDescriptionVisibility(it) @@ -70,16 +78,34 @@ class PersonalizeFragment : Fragment() { }) paramsVM.seError.observe(viewLifecycleOwner, Observer { showSnackbarMessage(it) }) - fab_action?.setOnClickListener { - val cardConfig = personalizeVM.createCardConfig(personalizeVM.createConfig(blockList)) - paramsVM.attachToPayload(mutableMapOf(PayloadKey.cardConfig to cardConfig)) - paramsVM.invokeMainAction() - } + actionFab.setOnClickListener { paramsVM.invokeMainAction() } } protected fun showSnackbarMessage(message: String) { Snackbar.make(mainView, message, BaseTransientBottomBar.LENGTH_SHORT).show() } + + override fun showActionFab(show: Boolean) { + if (show) actionFab.show() else actionFab.hide() + } + + override fun showSnackbar(id: Id) { +// MainResourceHolder.safeGet<>() + when (id) { + CardError.NotPersonalized -> showSnackbar(R.string.card_error_not_personalized) + ItemError.BadSeries -> showSnackbar(R.string.card_error_bad_series) + ItemError.BadCardNumber -> showSnackbar(R.string.card_error_bad_series_number) + else -> showSnackbar(requireContext().getString(R.string.unknown)) + } + } + + override fun showSnackbar(id: Int) { + showSnackbar(requireContext().getString(id)) + } + + override fun showSnackbar(message: String) { + Snackbar.make(mainView, message, BaseTransientBottomBar.LENGTH_SHORT).show() + } } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeViewModel.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeViewModel.kt index 8449ddcfad..b2c7ec7fce 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeViewModel.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizeViewModel.kt @@ -4,10 +4,9 @@ import android.view.View import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider -import com.google.gson.Gson -import com.tangem.commands.personalization.entities.CardConfig import com.tangem.tangemtest._arch.structure.abstraction.BaseItem -import com.tangem.tangemtest._arch.structure.abstraction.Block +import com.tangem.tangemtest._arch.structure.abstraction.Item +import com.tangem.tangemtest._arch.structure.abstraction.iterate import com.tangem.tangemtest.ucase.variants.personalize.converter.PersonalizeConfigConverter import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizeConfig @@ -20,32 +19,14 @@ class PersonalizeViewModelFactory(private val config: PersonalizeConfig) : ViewM class PersonalizeViewModel(private val config: PersonalizeConfig) : ViewModel() { - val ldBlockList: MutableLiveData> by lazy { MutableLiveData(initBlockList()) } + val ldBlockList: MutableLiveData> by lazy { MutableLiveData(initBlockList()) } - private fun initBlockList(): List = createBlocksFromConfig(config) - - fun createBlocksFromConfig(config: PersonalizeConfig): List { - return PersonalizeConfigConverter().toBlock(config) - } - - fun createConfig(blocList: List): PersonalizeConfig { - return PersonalizeConfigConverter().toConfig(blocList, PersonalizeConfig()) - } - - fun createCardConfig(config: PersonalizeConfig): CardConfig { - return PersonalizeConfigConverter().createCardConfig(config) - } - - fun convertToJson(config: PersonalizeConfig): String { - return Gson().toJson(config) - } + private fun initBlockList(): List = PersonalizeConfigConverter().convert(config) fun toggleDescriptionVisibility(state: Boolean) { - ldBlockList.value?.forEach { block -> - block.itemList.forEach { item -> - val vm = item as? BaseItem<*> ?: return@forEach - vm.viewModel.viewState.descriptionVisibility = if (state) View.VISIBLE else View.GONE - } + ldBlockList.value?.iterate { + val baseItem = it as? BaseItem<*> ?: return@iterate + baseItem.viewModel.viewState.descriptionVisibility = if (state) View.VISIBLE else View.GONE } } } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/abstraction/ViewWidget.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/abstraction/ViewWidget.kt index 6295598d1f..7926c4a0cf 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/abstraction/ViewWidget.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/abstraction/ViewWidget.kt @@ -30,6 +30,12 @@ abstract class BaseWidget( ) : ViewWidget, DataWidget { override val view: View = inflate(getLayoutId(), parent) + + init { + if (dataItem.viewModel.viewState.isHiddenField) { + view.visibility = View.GONE + } + } } abstract class BaseBlockWidget(parent: ViewGroup) : BlockViewWidget { diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/impl/item/EditTextWidget.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/impl/item/EditTextWidget.kt index a60b17fe68..c4bff5cfab 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/impl/item/EditTextWidget.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/impl/item/EditTextWidget.kt @@ -8,6 +8,7 @@ import com.google.android.material.textfield.TextInputLayout import com.tangem.tangemtest.R import com.tangem.tangemtest._arch.structure.impl.EditTextItem import com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.abstraction.getResNameId +import ru.dev.gbixahue.eu4d.lib.android._android.views.moveCursorToEnd import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf /** @@ -32,10 +33,13 @@ class EditTextWidget(parent: ViewGroup, data: EditTextItem) : DescriptionWidget< tilItem.hint = tilItem.context.getString(getResNameId()) etItem.setText(dataItem.viewModel.data) etItem.addTextChangedListener(watcher) - dataItem.viewModel.onDataUpdated = { - etItem.removeTextChangedListener(watcher) - etItem.setText(it) - etItem.addTextChangedListener(watcher) - } + dataItem.viewModel.onDataUpdated = { silentUpdate(it) } + } + + private fun silentUpdate(value: String?) { + etItem.removeTextChangedListener(watcher) + etItem.setText(value) + etItem.moveCursorToEnd() + etItem.addTextChangedListener(watcher) } } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/impl/item/NumberWidget.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/impl/item/NumberWidget.kt index 0c77806970..794c4c1ea0 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/impl/item/NumberWidget.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/widgets/impl/item/NumberWidget.kt @@ -1,13 +1,17 @@ package com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.impl.item import android.text.Editable +import android.text.InputFilter import android.text.TextWatcher import android.view.ViewGroup import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputLayout import com.tangem.tangemtest.R import com.tangem.tangemtest._arch.structure.impl.NumberItem +import com.tangem.tangemtest.ucase.variants.personalize.CardNumber import com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.abstraction.getResNameId +import ru.dev.gbixahue.eu4d.lib.android._android.views.addInputFilter +import ru.dev.gbixahue.eu4d.lib.android._android.views.moveCursorToEnd import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf /** @@ -21,7 +25,7 @@ class NumberWidget(parent: ViewGroup, data: NumberItem) : DescriptionWidget(parent, data) { +class SpinnerWidget(parent: ViewGroup, listItem: ListItem) : DescriptionWidget(parent, listItem) { override fun getLayoutId(): Int = R.layout.w_personalize_item_spinner + private val data: ListValueWrapper = listItem.getData()!! + private val spItem = view.findViewById(R.id.sp_item) - private val spAdapter = SpItemAdapter(dataItem.viewModel.data?.itemList) + private val spAdapter = SpItemAdapter(data.itemList) private val onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onNothingSelected(parent: AdapterView<*>?) {} override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - val vmData = dataItem.viewModel.data ?: return - - vmData.selectedItem = vmData.itemList[position] - dataItem.viewModel.updateDataByView(vmData) + data.selectedItem = data.itemList[position] + dataItem.viewModel.updateDataByView(data) } } @@ -38,6 +38,9 @@ class SpinnerWidget(parent: ViewGroup, data: ListItem) : DescriptionWidget(R.id.tv_name) name.setText(getResNameId()) spItem.adapter = spAdapter + spAdapter.getItemPosition(stringOf(data.selectedItem))?.let { + spItem.setSelection(it) + } spItem.onItemSelectedListener = onItemSelectedListener dataItem.viewModel.onDataUpdated = { it?.apply { @@ -81,4 +84,9 @@ class SpItemAdapter(list: List?) : BaseAdapter() { override fun getItemId(position: Int): Long = position.toLong() override fun getCount(): Int = itemList.size + + fun getItemPosition(item: String): Int? { + val kv = itemList.firstOrNull { it.value == item } ?: return null + return itemList.indexOf(kv) + } } \ No newline at end of file diff --git a/tangem-demo/src/main/res/values/strings.xml b/tangem-demo/src/main/res/values/strings.xml index 3d2be7b86b..5cb0f4053a 100644 --- a/tangem-demo/src/main/res/values/strings.xml +++ b/tangem-demo/src/main/res/values/strings.xml @@ -8,6 +8,8 @@ Docs Your card hasn\'t been personalized yet. You need to run personalize command first. + Wrong Series + Wrong Series and Number Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit diff --git a/tangem-demo/src/main/res/values/strings_personalization.xml b/tangem-demo/src/main/res/values/strings_personalization.xml index 365ba71b3b..f43540df2c 100644 --- a/tangem-demo/src/main/res/values/strings_personalization.xml +++ b/tangem-demo/src/main/res/values/strings_personalization.xml @@ -17,6 +17,7 @@ ​ Series Number + Batch ID Curve Blockchain Custom blockchain @@ -55,7 +56,7 @@ Forbid default PIN Smart Security Delay Protect issuer data against replay - Security delay if validated + Skip security delay if validated Skip PIN2 and CVC if validated Skip security delay on linked terminal Restrict overwrite extra issuer data @@ -86,6 +87,7 @@ ​ + Elliptic curve used for all wallet key operations. Supported curves: ‘secp256k1’, ‘ed25519’. Name of the blockchain. It\'s just a textfield in the card. It\'s needed for host app to tell what blockchain should it use. You can use this field, to create something special