Updated on 2026-08-14

This commit is contained in:
Tangem 2020-04-01 17:53:50 +03:00
parent faccc67704
commit 26adeb67ce
12 changed files with 112 additions and 31 deletions

View file

@ -11,7 +11,7 @@ import com.tangem.tangemtest.ucase.variants.personalize.dto.DefaultPersonalizePa
*/
class PersonalizeAction : BaseAction() {
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
val cardConfig = attrs.payload.remove(PayloadKey.CardConfig) as? CardConfig
val cardConfig = attrs.payload.remove(PayloadKey.cardConfig) as? CardConfig
?: throw IllegalArgumentException("CardConfig must be in the payloads of the ParamsManager")
val issuer = DefaultPersonalizeParams.issuer()

View file

@ -30,9 +30,10 @@ interface ItemsManager : PayloadHolder {
interface PayloadKey {
companion object {
val CardConfig: String = "cardConfig"
val IncominJson: String = "incomingJson"
val Card = "card"
val cardConfig: String = "cardConfig"
val incomingJson: String = "incomingJson"
val card = "card"
val actionView = "actionView"
}
}

View file

@ -1,12 +1,17 @@
package com.tangem.tangemtest.ucase.domain.paramsManager.triggers.afterAction
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.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
import com.tangem.tasks.ScanEvent
import com.tangem.tasks.TaskEvent
import ru.dev.gbixahue.eu4d.lib.android.global.threading.postUI
/**
[REDACTED_AUTHOR]
@ -17,10 +22,19 @@ class AfterScanModifier : AfterActionModification {
return if (taskEvent is TaskEvent.Event && taskEvent.data is ScanEvent.OnReadEvent) {
val card = (taskEvent.data as ScanEvent.OnReadEvent).card
payload.set(PayloadKey.Card, card)
val actionView = payload.remove(PayloadKey.actionView) as? ActionView ?: return listOf()
if (isPersonalized(card)) {
actionView.showSnackbar(CardError.NotPersonalized)
return listOf()
}
payload.set(PayloadKey.card, card)
foundItem.setData(card.cardId)
postUI { actionView.showActionFab(true) }
listOf(foundItem)
} else listOf()
}
private fun isPersonalized(card: Card): Boolean = card.status == CardStatus.NotPersonalized
}

View file

@ -27,7 +27,7 @@ class SignScanConsequence: ItemsChangeConsequence {
val hashItem = itemList.findDataItem(TlvId.TransactionOutHash) ?: return null
val affectedItems = mutableListOf(hashItem)
val card = payload.remove(PayloadKey.Card) as Card?
val card = payload.remove(PayloadKey.card) as Card?
if (card == null) {
hashItem.restoreDefaultData()
} else {

View file

@ -0,0 +1,10 @@
package com.tangem.tangemtest.ucase.tunnel
import com.tangem.tangemtest._arch.structure.Id
/**
[REDACTED_AUTHOR]
*/
enum class CardError : Id {
NotPersonalized
}

View file

@ -0,0 +1,14 @@
package com.tangem.tangemtest.ucase.tunnel
import com.tangem.tangemtest._arch.structure.Id
interface ViewScreen
interface SnackbarHolder {
fun showSnackbar(message: String)
fun showSnackbar(id: Id)
}
interface ActionView : ViewScreen, SnackbarHolder {
fun showActionFab(enable: Boolean)
}

View file

@ -16,26 +16,31 @@ 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.Id
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
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.ui.widgets.ParameterWidget
import ru.dev.gbixahue.eu4d.lib.android._android.views.find
import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
import ru.dev.gbixahue.eu4d.lib.kotlin.common.LayoutHolder
/**
[REDACTED_AUTHOR]
*/
abstract class BaseCardActionFragment : Fragment(), LayoutHolder {
abstract class BaseCardActionFragment : Fragment(), LayoutHolder, ActionView {
protected val incomingParamsContainer: ViewGroup by lazy {
mainView.findViewById<LinearLayout>(R.id.ll_incoming_params_container)
}
protected val viewModel: ParamsViewModel by viewModels { ActionViewModelFactory(itemsManager) }
protected lateinit var mainView: View
protected val actionFab: FloatingActionButton by lazy { mainView.findViewById<FloatingActionButton>(R.id.fab_action) }
protected val paramsVM: ParamsViewModel by viewModels { ActionViewModelFactory(itemsManager) }
protected val widgetList = mutableListOf<ParameterWidget>()
private val itemsManager: ItemsManager by lazy { ParamsManagerFactory.createFactory().get(getAction())!! }
@ -50,23 +55,26 @@ abstract class BaseCardActionFragment : Fragment(), LayoutHolder {
super.onViewCreated(view, savedInstanceState)
Log.d(this, "onViewCreated")
viewModel.setCardManager(CardManager.init(requireActivity()))
viewLifecycleOwner.lifecycle.addObserver(paramsVM)
paramsVM.setCardManager(CardManager.init(requireActivity()))
paramsVM.attachToPayload(mutableMapOf(PayloadKey.actionView to this as ActionView))
initFab()
showActionFab(false)
createWidgets { subscribeToViewModelChanges() }
}
private fun initFab() {
Log.d(this, "initFab")
mainView.find<FloatingActionButton>(R.id.fab_action)?.setOnClickListener { viewModel.invokeMainAction() }
actionFab.setOnClickListener { paramsVM.invokeMainAction() }
}
private fun createWidgets(widgetCreatedCallback: () -> Unit) {
Log.d(this, "createWidgets")
viewModel.ldParams.observe(viewLifecycleOwner, Observer { itemList ->
paramsVM.ldParams.observe(viewLifecycleOwner, Observer { itemList ->
itemList.forEach { param ->
val widget = ParameterWidget(inflateParamView(incomingParamsContainer), param)
widget.onValueChanged = { id, value -> viewModel.userChangedItem(id, value) }
widget.onActionBtnClickListener = viewModel.getItemAction(param.id)
widget.onValueChanged = { id, value -> paramsVM.userChangedItem(id, value) }
widget.onActionBtnClickListener = paramsVM.getItemAction(param.id)
widgetList.add(widget)
}
widgetCreatedCallback()
@ -83,18 +91,18 @@ abstract class BaseCardActionFragment : Fragment(), LayoutHolder {
protected open fun listenResponse() {
val tvResponse by lazy { mainView.findViewById<TextView>(R.id.tv_action_response_json) }
viewModel.ldResponse.observe(viewLifecycleOwner, Observer {
paramsVM.ldResponse.observe(viewLifecycleOwner, Observer {
Log.d(this, "action response: ${if (it.length > 50) it.substring(0..50) else it}")
tvResponse.text = it
})
}
protected open fun listenError() {
viewModel.seError.observe(viewLifecycleOwner, Observer { showSnackbarMessage(it) })
paramsVM.seError.observe(viewLifecycleOwner, Observer { showSnackbar(it) })
}
protected open fun listenChangedItems() {
viewModel.seChangedItems.observe(viewLifecycleOwner, Observer { itemList ->
paramsVM.seChangedItems.observe(viewLifecycleOwner, Observer { itemList ->
itemList.forEach { item ->
Log.d(this, "item changed from VM - name: ${item.id}")
val dataItem = item as? BaseItem<Any?> ?: return@Observer
@ -111,10 +119,6 @@ abstract class BaseCardActionFragment : Fragment(), LayoutHolder {
})
}
protected fun showSnackbarMessage(message: String) {
Snackbar.make(mainView, message, BaseTransientBottomBar.LENGTH_SHORT).show()
}
private fun inflateParamView(where: ViewGroup): ViewGroup {
val inflater = LayoutInflater.from(where.context)
val view = inflater.inflate(R.layout.w_card_incoming_param, where, false)
@ -122,5 +126,21 @@ abstract class BaseCardActionFragment : Fragment(), LayoutHolder {
return view as ViewGroup
}
override fun showActionFab(enable: Boolean) {
if (enable) actionFab.show() else actionFab.hide()
}
override fun showSnackbar(id: Id) {
// MainResourceHolder.safeGet<>()
when (id) {
CardError.NotPersonalized -> showSnackbar(requireContext().getString(R.string.card_error_not_personalized))
else -> showSnackbar(requireContext().getString(R.string.unknown))
}
}
override fun showSnackbar(message: String) {
Snackbar.make(mainView, message, BaseTransientBottomBar.LENGTH_SHORT).show()
}
abstract fun getAction(): ActionType
}

View file

@ -1,18 +1,18 @@
package com.tangem.tangemtest.ucase.ui
import androidx.annotation.UiThread
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.*
import com.google.gson.Gson
import com.tangem.CardManager
import com.tangem.commands.Card
import com.tangem.tangemtest._arch.SingleLiveEvent
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.commons.performAction
import com.tangem.tangemtest.ucase.domain.paramsManager.ItemsManager
import com.tangem.tangemtest.ucase.domain.responses.GsonInitializer
import com.tangem.tangemtest.ucase.tunnel.ViewScreen
import com.tangem.tasks.ScanEvent
import com.tangem.tasks.TaskError
import com.tangem.tasks.TaskEvent
@ -25,11 +25,12 @@ class ActionViewModelFactory(private val manager: ItemsManager) : ViewModelProvi
override fun <T : ViewModel?> create(modelClass: Class<T>): T = ParamsViewModel(manager) as T
}
class ParamsViewModel(val itemsManager: ItemsManager) : ViewModel() {
class ParamsViewModel(private val itemsManager: ItemsManager) : ViewModel(), LifecycleObserver {
val ldCard = MutableLiveData<Card>()
val ldIsVerified = MutableLiveData<Boolean>()
val ldResponse = MutableLiveData<String>()
val ldReadResponse = MutableLiveData<String>()
val ldParams = MutableLiveData(itemsManager.getItems())
val seError: MutableLiveData<String> = SingleLiveEvent()
@ -51,8 +52,7 @@ class ParamsViewModel(val itemsManager: ItemsManager) : ViewModel() {
}
//invokes Scan, Sign etc...
fun invokeMainAction(payload: MutableMap<String, Any?> = mutableMapOf()) {
itemsManager.attachPayload(payload)
fun invokeMainAction() {
performAction(itemsManager, cardManager) { paramsManager, cardManager ->
paramsManager.invokeMainAction(cardManager) { response, listOfChangedParams ->
notifier.handleActionResult(response, listOfChangedParams)
@ -69,6 +69,17 @@ class ParamsViewModel(val itemsManager: ItemsManager) : ViewModel() {
}
}
}
fun attachToPayload(payload: Payload) {
itemsManager.attachPayload(payload)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun viewOnDestroy() {
val keyList = mutableListOf<String>()
itemsManager.payload.filterValues { it is ViewScreen }.forEach { keyList.add(it.key) }
keyList.forEach { itemsManager.payload.remove(it) }
}
}
internal class Notifier(private val vm: ParamsViewModel) {
@ -99,7 +110,7 @@ internal class Notifier(private val vm: ParamsViewModel) {
when (event) {
is ScanEvent.OnReadEvent -> {
vm.ldCard.postValue(event.card)
vm.ldResponse.postValue(gson.toJson(event))
vm.ldReadResponse.postValue(gson.toJson(event))
}
is ScanEvent.OnVerifyEvent -> {
vm.ldIsVerified.postValue(true)

View file

@ -175,7 +175,7 @@ class PersonalizeConfigConverter {
}
private fun addPayload(block: Block, from: PersonalizeConfig) {
block.payload[PayloadKey.IncominJson] = from
block.payload[PayloadKey.incomingJson] = from
}
private fun createItem(block: ListItemBlock, id: Id) {

View file

@ -72,7 +72,8 @@ class PersonalizeFragment : Fragment() {
fab_action?.setOnClickListener {
val cardConfig = personalizeVM.createCardConfig(personalizeVM.createConfig(blockList))
paramsVM.invokeMainAction(mutableMapOf(PayloadKey.CardConfig to cardConfig))
paramsVM.attachToPayload(mutableMapOf(PayloadKey.cardConfig to cardConfig))
paramsVM.invokeMainAction()
}
}

View file

@ -1,5 +1,7 @@
package com.tangem.tangemtest.ucase.variants.scan.ui
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.lifecycle.Observer
import com.tangem.tangemtest.R
@ -17,10 +19,16 @@ class ScanActionFragment : BaseCardActionFragment() {
override fun getAction(): ActionType = ActionType.Scan
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
showActionFab(true)
}
override fun listenResponse() {
val tvStub = mainView.findViewById<TextView>(R.id.tv_screen_stub)
val tvResponse by lazy { mainView.findViewById<TextView>(R.id.tv_action_response_json) }
viewModel.ldResponse.observe(viewLifecycleOwner, Observer {
paramsVM.ldReadResponse.observe(viewLifecycleOwner, Observer {
Log.d(this, "action response: ${if (it.length > 50) it.substring(0..50) else it}")
tvStub.show(false)
tvResponse.text = it

View file

@ -7,4 +7,6 @@
<string name="unknown">unknown</string>
<string name="switch_description">Docs</string>
<string name="card_error_not_personalized">The card not personalized</string>
</resources>