Updated on 2026-08-14

This commit is contained in:
Tangem 2020-04-01 14:57:53 +03:00
parent 61cd81c4fc
commit 8b1440146c
22 changed files with 229 additions and 201 deletions

View file

@ -11,6 +11,12 @@ typealias Payload = MutableMap<String, Any?>
interface PayloadHolder {
val payload: Payload
fun get(key: String): Any? = payload[key]
fun remove(key: String): Any? = payload.remove(key)
fun set(key: String, value: Any?) {
payload[key] = value
}
}
interface ItemListHolder<I> {

View file

@ -18,4 +18,14 @@ abstract class BaseItem<D>(
) : Item, DataHolder<ItemViewModel<D>> {
override var parent: Item? = null
override val payload: Payload = mutableMapOf()
fun getData(): D? = viewModel.data
fun setData(value: D?) {
viewModel.data = value
}
fun restoreDefaultData(){
setData(viewModel.defaultData)
}
}

View file

@ -3,10 +3,11 @@ package com.tangem.tangemtest.ucase.domain.actions
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.Item
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
import com.tangem.tangemtest.ucase.domain.paramsManager.triggers.afterAction.AfterActionModification
import com.tangem.tangemtest.ucase.domain.paramsManager.triggers.changeConsequence.ParamsChangeConsequence
import com.tangem.tangemtest.ucase.domain.paramsManager.triggers.changeConsequence.ItemsChangeConsequence
import com.tangem.tasks.TaskEvent
/**
@ -17,28 +18,29 @@ import com.tangem.tasks.TaskEvent
*/
data class AttrForAction(
val cardManager: CardManager,
val paramsList: List<Item>,
val itemList: List<Item>,
val payload: Payload,
val consequence: ParamsChangeConsequence?
val consequence: ItemsChangeConsequence?
)
interface CardAction {
fun executeMainAction(attrs: AttrForAction, callback: ActionCallback)
fun getActionByTag(id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? = null
interface Action {
fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback)
fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? = null
}
abstract class BaseCardAction : CardAction {
protected open fun handleResponse(
abstract class BaseAction : Action {
protected open fun handleResult(
payload: PayloadHolder,
taskEvent: TaskEvent<*>,
modifier: AfterActionModification?,
attrs: AttrForAction,
callback: ActionCallback
) {
val allModifiedParams = mutableListOf<Item>()
modifier?.modify(taskEvent, attrs.paramsList)?.forEach { parameter ->
allModifiedParams.add(parameter)
attrs.consequence?.affectChanges(parameter, attrs.paramsList)?.let { allModifiedParams.addAll(it) }
val modifiedItems = mutableListOf<Item>()
modifier?.modify(payload, taskEvent, attrs.itemList)?.forEach { item ->
modifiedItems.add(item)
attrs.consequence?.affectChanges(payload, item, attrs.itemList)?.let { modifiedItems.addAll(it) }
}
callback(taskEvent, allModifiedParams)
callback(taskEvent, modifiedItems)
}
}

View file

@ -1,24 +1,25 @@
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.ucase.domain.paramsManager.ActionCallback
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataParameter
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem
import com.tangem.tangemtest.ucase.variants.TlvId
/**
[REDACTED_AUTHOR]
*/
class DepesonalizeAction : BaseCardAction() {
override fun executeMainAction(attrs: AttrForAction, callback: ActionCallback) {
val item = attrs.paramsList.findDataParameter(TlvId.CardId) ?: return
class DepesonalizeAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
val item = attrs.itemList.findDataItem(TlvId.CardId) ?: return
val cardId = item.viewModel.data as? String ?: return
attrs.cardManager.depersonalize(cardId) { handleResponse(it, null, attrs, callback) }
attrs.cardManager.depersonalize(cardId) { handleResult(payload, it, null, attrs, callback) }
}
override fun getActionByTag(id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
return when (id) {
TlvId.CardId -> { callback -> ScanAction().executeMainAction(attrs, callback) }
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
else -> null
}
}

View file

@ -1,15 +1,17 @@
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.ucase.domain.paramsManager.ActionCallback
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
import com.tangem.tangemtest.ucase.variants.personalize.dto.DefaultPersonalizeParams
/**
[REDACTED_AUTHOR]
*/
class PersonalizeAction : BaseCardAction() {
override fun executeMainAction(attrs: AttrForAction, callback: ActionCallback) {
val cardConfig = attrs.payload.remove(cardConfig) as? CardConfig
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 issuer = DefaultPersonalizeParams.issuer()
@ -17,11 +19,7 @@ class PersonalizeAction : BaseCardAction() {
val manufacturer = DefaultPersonalizeParams.manufacturer()
attrs.cardManager.personalize(cardConfig, issuer, manufacturer, acquirer) {
handleResponse(it, null, attrs, callback)
handleResult(payload, it, null, attrs, callback)
}
}
companion object {
val cardConfig = "cardConfig"
}
}

View file

@ -1,13 +1,14 @@
package com.tangem.tangemtest.ucase.domain.actions
import com.tangem.tangemtest._arch.structure.PayloadHolder
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
import com.tangem.tangemtest.ucase.domain.paramsManager.triggers.afterAction.AfterScanModifier
/**
[REDACTED_AUTHOR]
*/
class ScanAction : BaseCardAction() {
override fun executeMainAction(attrs: AttrForAction, callback: ActionCallback) {
attrs.cardManager.scanCard { handleResponse(it, AfterScanModifier(), attrs, callback) }
class ScanAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
attrs.cardManager.scanCard { handleResult(payload, it, AfterScanModifier(), attrs, callback) }
}
}

View file

@ -1,32 +1,28 @@
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.ucase.domain.paramsManager.ActionCallback
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataParameter
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem
import com.tangem.tangemtest.ucase.variants.TlvId
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
/**
[REDACTED_AUTHOR]
*/
class SignAction : BaseCardAction() {
override fun executeMainAction(attrs: AttrForAction, callback: ActionCallback) {
val dataForHashing = attrs.paramsList.findDataParameter(TlvId.TransactionOutHash) ?: return
class SignAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
val dataForHashing = attrs.itemList.findDataItem(TlvId.TransactionOutHash) ?: return
val hash = dataForHashing.getData() as? ByteArray ?: return
val cardId = attrs.itemList.findDataItem(TlvId.CardId)?.viewModel?.data ?: return
val arHashes = createHashes(stringOf(dataForHashing.viewModel.data))
val cardId = attrs.paramsList.findDataParameter(TlvId.CardId)?.viewModel?.data ?: return
attrs.cardManager.sign(arHashes, stringOf(cardId)) { handleResponse(it, null, attrs, callback) }
attrs.cardManager.sign(arrayOf(hash), stringOf(cardId)) { handleResult(payload, it, null, attrs, callback) }
}
override fun getActionByTag(id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
return when (id) {
TlvId.CardId -> { callback -> ScanAction().executeMainAction(attrs, callback) }
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
else -> null
}
}
private fun createHashes(value: String): Array<ByteArray> {
return arrayOf(value.toByteArray())
}
}

View file

@ -1,24 +1,24 @@
package com.tangem.tangemtest.ucase.domain.paramsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.managers.DepersonalizeParamsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.managers.PersonalizeParamsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.managers.ScanParamsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.managers.SignParamsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.managers.DepersonalizeItemsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.managers.PersonalizeItemsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.managers.ScanItemsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.managers.SignItemsManager
import com.tangem.tangemtest.ucase.resources.ActionType
import ru.dev.gbixahue.eu4d.lib.kotlin.common.BaseTypedHolder
/**
[REDACTED_AUTHOR]
*/
class ParamsManagerFactory : BaseTypedHolder<ActionType, ParamsManager>() {
class ParamsManagerFactory : BaseTypedHolder<ActionType, ItemsManager>() {
companion object {
fun createFactory(): ParamsManagerFactory {
return ParamsManagerFactory().apply {
register(ActionType.Scan, ScanParamsManager())
register(ActionType.Sign, SignParamsManager())
register(ActionType.Personalize, PersonalizeParamsManager())
register(ActionType.Depersonalize, DepersonalizeParamsManager())
register(ActionType.Scan, ScanItemsManager())
register(ActionType.Sign, SignItemsManager())
register(ActionType.Personalize, PersonalizeItemsManager())
register(ActionType.Depersonalize, DepersonalizeItemsManager())
}
}
}

View file

@ -6,31 +6,41 @@ 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
typealias ActionResponse = TaskEvent<*>
typealias AffectedList = List<Item>
typealias AffectedParamsCallback = (AffectedList) -> Unit
typealias AffectedItemsCallback = (AffectedList) -> Unit
typealias ActionCallback = (ActionResponse, AffectedList) -> Unit
/**
[REDACTED_AUTHOR]
*/
interface ParamsManager : PayloadHolder {
interface ItemsManager : PayloadHolder {
fun parameterChanged(id: Id, value: Any?, callback: AffectedParamsCallback? = null)
fun getParams(): List<Item>
fun itemChanged(id: Id, value: Any?, callback: AffectedItemsCallback? = null)
fun getItems(): List<Item>
fun invokeMainAction(cardManager: CardManager, callback: ActionCallback)
fun getActionByTag(id: Id, cardManager: CardManager): ((ActionCallback) -> Unit)?
fun attachPayload(payload: Payload)
val consequence: ItemsChangeConsequence?
}
interface PayloadKey {
companion object {
val CardConfig: String = "cardConfig"
val IncominJson: String = "incomingJson"
val Card = "card"
}
}
fun List<Item>.findParameter(id: Id): Item? {
fun List<Item>.findItem(id: Id): Item? {
return firstOrNull { it.id == id }
}
fun List<Item>.findDataParameter(id: Id): BaseItem<Any?>? {
fun List<Item>.findDataItem(id: Id): BaseItem<Any?>? {
val item = firstOrNull { it.id == id }
return if (item is BaseItem<*>) item as BaseItem<Any?>
else null

View file

@ -0,0 +1,51 @@
package com.tangem.tangemtest.ucase.domain.paramsManager.managers
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.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
/**
[REDACTED_AUTHOR]
*/
abstract class BaseItemsManager(protected val action: Action) : ItemsManager {
protected val itemList: List<Item> by lazy { createItemsList() }
override val consequence: ItemsChangeConsequence? = null
override val payload: MutableMap<String, Any?> = mutableMapOf()
override fun itemChanged(id: Id, value: Any?, callback: AffectedItemsCallback?) {
if (itemList.isEmpty()) return
val foundItem = itemList.findDataItem(id) ?: return
foundItem.setData(value)
applyChangesByAffectedItems(foundItem, callback)
}
override fun getItems(): MutableList<Item> = itemList.toMutableList()
override fun getActionByTag(id: Id, cardManager: CardManager): ((ActionCallback) -> Unit)? = null
override fun attachPayload(payload: Payload) {
payload.forEach { this.payload[it.key] = it.value }
}
// Use it if current item needs to be affect any other items
protected open fun applyChangesByAffectedItems(param: Item, callback: AffectedItemsCallback?) {
consequence?.affectChanges(this, param, itemList)?.let { callback?.invoke(it) }
}
protected fun getAttrsForAction(cardManager: CardManager)
: AttrForAction = AttrForAction(cardManager, itemList, payload, consequence)
abstract fun createItemsList(): List<Item>
}

View file

@ -1,50 +0,0 @@
package com.tangem.tangemtest.ucase.domain.paramsManager.managers
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.ucase.domain.actions.AttrForAction
import com.tangem.tangemtest.ucase.domain.actions.CardAction
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
import com.tangem.tangemtest.ucase.domain.paramsManager.AffectedParamsCallback
import com.tangem.tangemtest.ucase.domain.paramsManager.ParamsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataParameter
import com.tangem.tangemtest.ucase.domain.paramsManager.triggers.changeConsequence.ParamsChangeConsequence
/**
[REDACTED_AUTHOR]
*/
abstract class BaseParamsManager(protected val action: CardAction) : ParamsManager {
override val payload: MutableMap<String, Any?> = mutableMapOf()
protected val paramsList: List<Item> by lazy { createParamsList() }
abstract fun createParamsList(): List<Item>
override fun parameterChanged(id: Id, value: Any?, callback: AffectedParamsCallback?) {
if (paramsList.isEmpty()) return
val foundParam = paramsList.findDataParameter(id) ?: return
foundParam.viewModel.data = value
applyChangesByAffectedParams(foundParam, callback)
}
override fun getParams(): MutableList<Item> = paramsList.toMutableList()
override fun getActionByTag(id: Id, cardManager: CardManager): ((ActionCallback) -> Unit)? = null
override fun attachPayload(payload: Payload) {
payload.forEach { this.payload[it.key] = it.value }
}
// Use it if current parameter needs to be affect any other parameters
protected open fun applyChangesByAffectedParams(param: Item, callback: AffectedParamsCallback?) {
getChangeConsequence()?.affectChanges(param, paramsList)?.let { callback?.invoke(it) }
}
protected open fun getChangeConsequence(): ParamsChangeConsequence? = null
protected fun getAttrsForAction(cardManager: CardManager)
: AttrForAction = AttrForAction(cardManager, paramsList, payload, getChangeConsequence())
}

View file

@ -11,16 +11,16 @@ import com.tangem.tangemtest.ucase.variants.TlvId
/**
[REDACTED_AUTHOR]
*/
class DepersonalizeParamsManager : BaseParamsManager(DepesonalizeAction()) {
override fun createParamsList(): List<Item> {
class DepersonalizeItemsManager : BaseItemsManager(DepesonalizeAction()) {
override fun createItemsList(): List<Item> {
return listOf(EditTextItem(TlvId.CardId, null))
}
override fun invokeMainAction(cardManager: CardManager, callback: ActionCallback) {
action.executeMainAction(getAttrsForAction(cardManager), callback)
action.executeMainAction(this, getAttrsForAction(cardManager), callback)
}
override fun getActionByTag(id: Id, cardManager: CardManager): ((ActionCallback) -> Unit)? {
return action.getActionByTag(id, getAttrsForAction(cardManager))
return action.getActionByTag(this, id, getAttrsForAction(cardManager))
}
}

View file

@ -10,12 +10,12 @@ import com.tangem.tangemtest.ucase.variants.TlvId
/**
[REDACTED_AUTHOR]
*/
class PersonalizeParamsManager : BaseParamsManager(PersonalizeAction()) {
override fun createParamsList(): List<Item> {
class PersonalizeItemsManager : BaseItemsManager(PersonalizeAction()) {
override fun createItemsList(): List<Item> {
return listOf(EditTextItem(TlvId.CardId))
}
override fun invokeMainAction(cardManager: CardManager, callback: ActionCallback) {
action.executeMainAction(getAttrsForAction(cardManager), callback)
action.executeMainAction(this, getAttrsForAction(cardManager), callback)
}
}

View file

@ -8,10 +8,10 @@ import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
/**
[REDACTED_AUTHOR]
*/
class ScanParamsManager : BaseParamsManager(ScanAction()) {
override fun createParamsList(): List<Item> = listOf()
class ScanItemsManager : BaseItemsManager(ScanAction()) {
override fun createItemsList(): List<Item> = listOf()
override fun invokeMainAction(cardManager: CardManager, callback: ActionCallback) {
action.executeMainAction(getAttrsForAction(cardManager), callback)
action.executeMainAction(this, getAttrsForAction(cardManager), callback)
}
}

View file

@ -6,13 +6,18 @@ import com.tangem.tangemtest._arch.structure.abstraction.Item
import com.tangem.tangemtest._arch.structure.impl.EditTextItem
import com.tangem.tangemtest.ucase.domain.actions.SignAction
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
import com.tangem.tangemtest.ucase.domain.paramsManager.triggers.changeConsequence.ItemsChangeConsequence
import com.tangem.tangemtest.ucase.domain.paramsManager.triggers.changeConsequence.SignScanConsequence
import com.tangem.tangemtest.ucase.variants.TlvId
/**
[REDACTED_AUTHOR]
*/
class SignParamsManager : BaseParamsManager(SignAction()) {
override fun createParamsList(): List<Item> {
class SignItemsManager : BaseItemsManager(SignAction()) {
override val consequence: ItemsChangeConsequence? by lazy { SignScanConsequence() }
override fun createItemsList(): List<Item> {
return listOf(
EditTextItem(TlvId.CardId, null),
EditTextItem(TlvId.TransactionOutHash, "Data used for hashing")
@ -20,10 +25,10 @@ class SignParamsManager : BaseParamsManager(SignAction()) {
}
override fun invokeMainAction(cardManager: CardManager, callback: ActionCallback) {
action.executeMainAction(getAttrsForAction(cardManager), callback)
action.executeMainAction(this, getAttrsForAction(cardManager), callback)
}
override fun getActionByTag(id: Id, cardManager: CardManager): ((ActionCallback) -> Unit)? {
return action.getActionByTag(id, getAttrsForAction(cardManager))
return action.getActionByTag(this, id, getAttrsForAction(cardManager))
}
}

View file

@ -1,15 +1,16 @@
package com.tangem.tangemtest.ucase.domain.paramsManager.triggers.afterAction
import com.tangem.tangemtest._arch.structure.PayloadHolder
import com.tangem.tangemtest._arch.structure.abstraction.Item
import com.tangem.tasks.TaskEvent
/**
[REDACTED_AUTHOR]
*
* The After Action Modification class family is intended for modifying parameters (if necessary)
* The After Action Modification class family is intended for modifying items (if necessary)
* after calling CardManager.anyAction.
* Returns a list of parameters that have been modified
* Returns a list of items that have been modified
*/
interface AfterActionModification {
fun modify(taskEvent: TaskEvent<*>, paramsList: List<Item>): List<Item>
fun modify(payload: PayloadHolder, taskEvent: TaskEvent<*>, itemList: List<Item>): List<Item>
}

View file

@ -1,7 +1,9 @@
package com.tangem.tangemtest.ucase.domain.paramsManager.triggers.afterAction
import com.tangem.tangemtest._arch.structure.PayloadHolder
import com.tangem.tangemtest._arch.structure.abstraction.Item
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataParameter
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem
import com.tangem.tangemtest.ucase.variants.TlvId
import com.tangem.tasks.ScanEvent
import com.tangem.tasks.TaskEvent
@ -10,12 +12,14 @@ import com.tangem.tasks.TaskEvent
[REDACTED_AUTHOR]
*/
class AfterScanModifier : AfterActionModification {
override fun modify(taskEvent: TaskEvent<*>, paramsList: List<Item>): List<Item> {
val parameter = paramsList.findDataParameter(TlvId.CardId) ?: return listOf()
override fun modify(payload: PayloadHolder, taskEvent: TaskEvent<*>, itemList: List<Item>): List<Item> {
val foundItem = itemList.findDataItem(TlvId.CardId) ?: return listOf()
return if (taskEvent is TaskEvent.Event && taskEvent.data is ScanEvent.OnReadEvent) {
parameter.viewModel.data = (taskEvent.data as ScanEvent.OnReadEvent).card.cardId
listOf(parameter)
val card = (taskEvent.data as ScanEvent.OnReadEvent).card
payload.set(PayloadKey.Card, card)
foundItem.setData(card.cardId)
listOf(foundItem)
} else listOf()
}

View file

@ -1,6 +1,13 @@
package com.tangem.tangemtest.ucase.domain.paramsManager.triggers.changeConsequence
import com.tangem.commands.Card
import com.tangem.commands.EllipticCurve
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.ucase.domain.paramsManager.PayloadKey
import com.tangem.tangemtest.ucase.domain.paramsManager.findDataItem
import com.tangem.tangemtest.ucase.variants.TlvId
/**
@ -9,16 +16,29 @@ import com.tangem.tangemtest.ucase.variants.TlvId
* The ParamsChangeConsequence class family modifies parameters depending on the state
* of the incoming parameter
*/
interface ParamsChangeConsequence {
fun affectChanges(changedParameter: Item, paramsList: List<Item>): List<Item>
interface ItemsChangeConsequence {
fun affectChanges(payload: PayloadHolder, changedItem: Item, itemList: List<Item>): List<Item>?
}
class ExampleConsequenceForCardId : ParamsChangeConsequence {
override fun affectChanges(changedParameter: Item, paramsList: List<Item>): List<Item> {
if (changedParameter.id != TlvId.CardId) return listOf()
class SignScanConsequence: ItemsChangeConsequence {
val affectedList = paramsList.filter { it.id != changedParameter.id }
// affectedList.forEach { it.viewModel.data = changedParameter.viewModel.data?.hashCode() }
return affectedList
override fun affectChanges(payload: PayloadHolder, changedItem: Item, itemList: List<Item>): List<Item>? {
if (changedItem.id != TlvId.CardId) return null
val hashItem = itemList.findDataItem(TlvId.TransactionOutHash) ?: return null
val affectedItems = mutableListOf(hashItem)
val card = payload.remove(PayloadKey.Card) as Card?
if (card == null) {
hashItem.restoreDefaultData()
} else {
val dataForHashing = hashItem.getData() as? String ?: "Any data mother...s"
val hashedData = when(card.curve) {
EllipticCurve.Secp256k1 -> dataForHashing.calculateSha256()
EllipticCurve.Ed25519 -> dataForHashing.calculateSha512()
else -> throw Exception("Can't calculate hash of a data with unknown card curve")
}
hashItem.setData(hashedData)
}
return affectedItems.toList()
}
}

View file

@ -18,7 +18,7 @@ import com.tangem.tangem_sdk_new.extensions.init
import com.tangem.tangemtest.R
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
import com.tangem.tangemtest._main.MainViewModel
import com.tangem.tangemtest.ucase.domain.paramsManager.ParamsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.ItemsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.ParamsManagerFactory
import com.tangem.tangemtest.ucase.resources.ActionType
import com.tangem.tangemtest.ucase.ui.widgets.ParameterWidget
@ -34,10 +34,10 @@ abstract class BaseCardActionFragment : Fragment(), LayoutHolder {
protected val incomingParamsContainer: ViewGroup by lazy {
mainView.findViewById<LinearLayout>(R.id.ll_incoming_params_container)
}
protected val viewModel: ParamsViewModel by viewModels { ActionViewModelFactory(paramsManager) }
protected val viewModel: ParamsViewModel by viewModels { ActionViewModelFactory(itemsManager) }
protected lateinit var mainView: View
private val paramsManager: ParamsManager by lazy { ParamsManagerFactory.createFactory().get(getAction())!! }
private val itemsManager: ItemsManager by lazy { ParamsManagerFactory.createFactory().get(getAction())!! }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
Log.d(this, "onCreateView")
@ -61,12 +61,12 @@ abstract class BaseCardActionFragment : Fragment(), LayoutHolder {
private fun createWidgets(callback: (List<ParameterWidget>) -> Unit) {
Log.d(this, "createWidgets")
viewModel.ldParams.observe(viewLifecycleOwner, Observer { paramsList ->
viewModel.ldParams.observe(viewLifecycleOwner, Observer { itemList ->
val widgetList = mutableListOf<ParameterWidget>()
paramsList.forEach { param ->
itemList.forEach { param ->
val widget = ParameterWidget(inflateParamView(incomingParamsContainer), param)
widget.onValueChanged = { id, value -> viewModel.userChangedParameter(id, value) }
widget.onActionBtnClickListener = viewModel.getParameterAction(param.id)
widget.onValueChanged = { id, value -> viewModel.userChangedItem(id, value) }
widget.onActionBtnClickListener = viewModel.getItemAction(param.id)
widgetList.add(widget)
}
callback(widgetList)
@ -82,11 +82,11 @@ abstract class BaseCardActionFragment : Fragment(), LayoutHolder {
tvResponse.text = it
})
viewModel.seError.observe(viewLifecycleOwner, Observer { showSnackbarMessage(it) })
viewModel.changedParameters.observe(viewLifecycleOwner, Observer { itemList ->
viewModel.seChangedItems.observe(viewLifecycleOwner, Observer { itemList ->
itemList.forEach { item ->
Log.d(this, "parameter changed from VM - name: ${item.id}")
Log.d(this, "item changed from VM - name: ${item.id}")
val dataItem = item as? BaseItem<Any?> ?: return@Observer
Log.d(this, "parameter changed from VM - name: ${dataItem.id}, value:${dataItem.viewModel.data}")
Log.d(this, "item changed from VM - name: ${dataItem.id}, value:${dataItem.viewModel.data}")
widgetList.firstOrNull { it.id == item.id }?.changeParamValue(item.viewModel.data)
}
})

View file

@ -11,7 +11,7 @@ import com.tangem.tangemtest._arch.SingleLiveEvent
import com.tangem.tangemtest._arch.structure.Id
import com.tangem.tangemtest._arch.structure.abstraction.Item
import com.tangem.tangemtest.commons.performAction
import com.tangem.tangemtest.ucase.domain.paramsManager.ParamsManager
import com.tangem.tangemtest.ucase.domain.paramsManager.ItemsManager
import com.tangem.tangemtest.ucase.domain.responses.GsonInitializer
import com.tangem.tasks.ScanEvent
import com.tangem.tasks.TaskError
@ -21,19 +21,19 @@ import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
/**
[REDACTED_AUTHOR]
*/
class ActionViewModelFactory(private val manager: ParamsManager) : ViewModelProvider.NewInstanceFactory() {
class ActionViewModelFactory(private val manager: ItemsManager) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T = ParamsViewModel(manager) as T
}
class ParamsViewModel(val paramsManager: ParamsManager) : ViewModel() {
class ParamsViewModel(val itemsManager: ItemsManager) : ViewModel() {
val ldCard = MutableLiveData<Card>()
val ldIsVerified = MutableLiveData<Boolean>()
val ldResponse = MutableLiveData<String>()
val ldParams = MutableLiveData(paramsManager.getParams())
val ldParams = MutableLiveData(itemsManager.getItems())
val seError: MutableLiveData<String> = SingleLiveEvent()
val changedParameters: MutableLiveData<List<Item>> = SingleLiveEvent()
val seChangedItems: MutableLiveData<List<Item>> = SingleLiveEvent()
private val notifier: Notifier = Notifier(this)
private lateinit var cardManager: CardManager
@ -42,29 +42,29 @@ class ParamsViewModel(val paramsManager: ParamsManager) : ViewModel() {
this.cardManager = cardManager
}
fun userChangedParameter(id: Id, value: Any?) {
parameterChanged(id, value)
fun userChangedItem(id: Id, value: Any?) {
itemChanged(id, value)
}
private fun parameterChanged(id: Id, value: Any?) {
paramsManager.parameterChanged(id, value) { notifier.notifyParameterChanges(it) }
private fun itemChanged(id: Id, value: Any?) {
itemsManager.itemChanged(id, value) { notifier.notifyItemsChanged(it) }
}
//invokes Scan, Sign etc...
fun invokeMainAction(payload: MutableMap<String, Any?> = mutableMapOf()) {
paramsManager.attachPayload(payload)
performAction(paramsManager, cardManager) { paramsManager, cardManager ->
itemsManager.attachPayload(payload)
performAction(itemsManager, cardManager) { paramsManager, cardManager ->
paramsManager.invokeMainAction(cardManager) { response, listOfChangedParams ->
notifier.handleActionResult(response, listOfChangedParams)
}
}
}
fun getParameterAction(id: Id): (() -> Unit)? {
val parameterFunction = paramsManager.getActionByTag(id, cardManager) ?: return null
fun getItemAction(id: Id): (() -> Unit)? {
val itemFunction = itemsManager.getActionByTag(id, cardManager) ?: return null
return {
parameterFunction { response, listOfChangedParams ->
itemFunction { response, listOfChangedParams ->
notifier.handleActionResult(response, listOfChangedParams)
}
}
@ -77,13 +77,13 @@ internal class Notifier(private val vm: ParamsViewModel) {
private val gson: Gson = GsonInitializer().gson
fun handleActionResult(response: TaskEvent<*>, list: List<Item>) {
notifyParameterChanges(list)
notifyItemsChanged(list)
handleResponse(response)
}
@UiThread
fun notifyParameterChanges(list: List<Item>) {
vm.changedParameters.postValue(list)
fun notifyItemsChanged(list: List<Item>) {
vm.seChangedItems.postValue(list)
}
fun handleResponse(response: TaskEvent<*>) {

View file

@ -10,6 +10,7 @@ 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.ucase.variants.personalize.dto.PersonalizeConfig
import java.util.*
@ -174,7 +175,7 @@ class PersonalizeConfigConverter {
}
private fun addPayload(block: Block, from: PersonalizeConfig) {
block.payload[Additional.JSON_INCOMING.name] = from
block.payload[PayloadKey.IncominJson] = from
}
private fun createItem(block: ListItemBlock, id: Id) {

View file

@ -16,9 +16,9 @@ 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._main.MainViewModel
import com.tangem.tangemtest.ucase.domain.actions.PersonalizeAction
import com.tangem.tangemtest.ucase.domain.paramsManager.ParamsManager
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.ui.ActionViewModelFactory
import com.tangem.tangemtest.ucase.ui.ParamsViewModel
@ -35,8 +35,8 @@ class PersonalizeFragment : Fragment() {
private val mainActivityVM: MainViewModel by activityViewModels()
private val personalizeVM: PersonalizeViewModel by viewModels { PersonalizeViewModelFactory(PersonalizeConfig()) }
private val paramsManager: ParamsManager by lazy { ParamsManagerFactory.createFactory().get(ActionType.Personalize)!! }
private val paramsVM: ParamsViewModel by viewModels() { ActionViewModelFactory(paramsManager) }
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<LinearLayout>(R.id.ll_container)
@ -72,41 +72,13 @@ class PersonalizeFragment : Fragment() {
fab_action?.setOnClickListener {
val cardConfig = personalizeVM.createCardConfig(personalizeVM.createConfig(blockList))
paramsVM.invokeMainAction(mutableMapOf(PersonalizeAction.cardConfig to cardConfig))
paramsVM.invokeMainAction(mutableMapOf(PayloadKey.CardConfig to cardConfig))
}
}
// private fun initCardManager(): CardManager? {
// val activity = activity ?: return null
// val nfcManager = NfcManager().apply {
// this.setCurrentActivity(activity)
// activity.lifecycle.addObserver(NfcLifecycleObserver(this))
// }
// val cardManagerDelegate = DefaultCardManagerDelegate(nfcManager.reader).apply {
// this.activity = activity
// }
// return CardManager(nfcManager.reader, cardManagerDelegate, DefaultPersonalizeParams.default()).apply {
// this.setTerminalKeysService(TerminalKeysStorage(activity.application))
// }
// }
protected fun showSnackbarMessage(message: String) {
Snackbar.make(mainView, message, BaseTransientBottomBar.LENGTH_SHORT).show()
}
// private fun getJsonFromAssets(context: Context, fileName: String): String? {
// return try {
// val stream: InputStream = context.assets.open(fileName)
// val size: Int = stream.available()
// val buffer = ByteArray(size)
// stream.read(buffer)
// stream.close()
// String(buffer, Charset.forName("UTF-8"))
// } catch (e: IOException) {
// e.printStackTrace()
// null
// }
// }
}