Updated on 2026-08-14

This commit is contained in:
Tangem 2020-03-25 14:06:08 +03:00
parent 7c6a986089
commit 1c554ecde7
17 changed files with 213 additions and 14 deletions

View file

@ -14,6 +14,7 @@ class AppTangemDemo : Application() {
override fun onCreate() {
super.onCreate()
AppTangemDemo.appInstance = this
setupLoggers()
}
@ -21,4 +22,8 @@ class AppTangemDemo : Application() {
Log.setLogger(TangemLogger())
ULog.setLogger(UnitLogger())
}
companion object {
lateinit var appInstance: AppTangemDemo
}
}

View file

@ -67,6 +67,7 @@ class EntryPointFragment : Fragment() {
NavigateOptions(ActionType.Scan, R.id.action_nav_entry_point_to_nav_scan),
NavigateOptions(ActionType.Sign, R.id.action_nav_entry_point_to_nav_sign),
NavigateOptions(ActionType.Personalize, R.id.action_nav_entry_point_to_nav_personalize),
NavigateOptions(ActionType.Depersonalize, R.id.action_nav_entry_point_to_nav_depersonalize),
NavigateOptions(ActionType.CreateWallet, R.id.action_nav_entry_point_to_nav_wallet_create),
NavigateOptions(ActionType.PurgeWallet, R.id.action_nav_entry_point_to_nav_wallet_purge),
NavigateOptions(ActionType.ReadIssuerData, R.id.action_nav_entry_point_to_nav_issuer_read_data),

View file

@ -1,13 +1,17 @@
package com.tangem.tangemtest.card_use_cases.domain.card_action
import com.tangem.CardManager
import com.tangem.commands.personalization.CardConfig
import com.tangem.common.tlv.TlvTag
import com.tangem.tangemtest.AppTangemDemo
import com.tangem.tangemtest.card_use_cases.domain.params_manager.ActionCallback
import com.tangem.tangemtest.card_use_cases.domain.params_manager.IncomingParameter
import com.tangem.tangemtest.card_use_cases.domain.params_manager.findParameter
import com.tangem.tangemtest.card_use_cases.domain.params_manager.modifiers.AfterActionModification
import com.tangem.tangemtest.card_use_cases.domain.params_manager.modifiers.AfterScanModifier
import com.tangem.tangemtest.card_use_cases.domain.params_manager.modifiers.ParamsChangeConsequence
import com.tangem.tangemtest.extensions.init
import com.tangem.tasks.ScanEvent
import com.tangem.tasks.TaskEvent
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
@ -74,6 +78,51 @@ class SignAction : BaseCardAction() {
class PersonalizeAction : BaseCardAction() {
override fun executeMainAction(attrs: AttrForAction, callback: ActionCallback) {
TODO("Not yet implemented")
ScanAction().executeMainAction(attrs) { response, b ->
when(response){
is TaskEvent.Event -> {
val taskEvent = response as TaskEvent.Event
val cardId = handleDataEvent(taskEvent.data)
if (cardId == null) {
handleResponse(response, null, attrs, callback)
return@executeMainAction
}
attrs.cardManager.personalize(CardConfig.init(AppTangemDemo.appInstance), cardId) {
handleResponse(it, null, attrs, callback)
}
}
is TaskEvent.Completion -> {
handleResponse(response, null, attrs, callback)
}
}
}
}
private fun handleDataEvent(event: Any?): String? {
return when (event) {
is ScanEvent.OnReadEvent -> {
event.card.cardId
}
else -> null
}
}
}
class DepesonalizeAction : BaseCardAction() {
override fun executeMainAction(attrs: AttrForAction, callback: ActionCallback) {
val cardId = attrs.paramsList.findParameter(TlvTag.CardId)?.data as? String ?: return
attrs.cardManager.depersonalize(cardId) { handleResponse(it, null, attrs, callback) }
}
override fun getActionByTag(tag: TlvTag, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
return when (tag) {
TlvTag.CardId -> { callback -> ScanAction().executeMainAction(attrs, callback) }
else -> null
}
}
}

View file

@ -14,6 +14,7 @@ class ParamsManagerFactory : BaseTypedHolder<ActionType, ParamsManager>() {
register(ActionType.Scan, ScanParamsManager())
register(ActionType.Sign, SignParamsManager())
register(ActionType.Personalize, PersonalizeParamsManager())
register(ActionType.Depersonalize, DepersonalizeParamsManager())
}
}
}

View file

@ -26,4 +26,5 @@ class AfterScanModifier : AfterActionModification {
listOf(parameter)
} else listOf()
}
}

View file

@ -94,6 +94,20 @@ class PersonalizeParamsManager : BaseParamsManager(PersonalizeAction()) {
}
override fun invokeMainAction(cardManager: CardManager, callback: ActionCallback) {
action.executeMainAction(getAttrsForAction(cardManager), callback)
}
}
class DepersonalizeParamsManager: BaseParamsManager(DepesonalizeAction()){
override fun createParamsList(): List<IncomingParameter> {
return listOf(IncomingParameter(TlvTag.CardId, null))
}
override fun invokeMainAction(cardManager: CardManager, callback: ActionCallback) {
action.executeMainAction(getAttrsForAction(cardManager), callback)
}
override fun getActionByTag(tag: TlvTag, cardManager: CardManager): ((ActionCallback) -> Unit)? {
return action.getActionByTag(tag, getAttrsForAction(cardManager))
}
}

View file

@ -0,0 +1,16 @@
package com.tangem.tangemtest.card_use_cases.ui.card.actions
import com.tangem.tangemtest.R
import com.tangem.tangemtest.card_use_cases.ui.card.BaseCardActionFragment
import com.tangem.tangemtest.commons.ActionType
/**
[REDACTED_AUTHOR]
*/
class DepesonalizeActionFragment : BaseCardActionFragment() {
override fun getLayoutId(): Int = R.layout.fg_depersonalize
override fun getAction(): ActionType = ActionType.Depersonalize
}

View file

@ -114,7 +114,7 @@ internal class Notifier(private val vm: ParamsViewModel) {
if (notShowedError == null) {
vm.seError.postValue("User was cancelled")
} else {
vm.seError.postValue("Error description not implemented. Code: ${notShowedError!!.code}")
vm.seError.postValue("${notShowedError!!::class.simpleName}")
notShowedError = null
}
}

View file

@ -10,9 +10,19 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
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._main.MainViewModel
import com.tangem.tangemtest.card_use_cases.domain.params_manager.ParamsManager
import com.tangem.tangemtest.card_use_cases.domain.params_manager.ParamsManagerFactory
import com.tangem.tangemtest.card_use_cases.ui.card.actions.ActionViewModelFactory
import com.tangem.tangemtest.card_use_cases.ui.card.actions.ParamsViewModel
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.WidgetBuilder
import com.tangem.tangemtest.commons.ActionType
import kotlinx.android.synthetic.main.fg_personalize.*
import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
import java.io.IOException
import java.io.InputStream
@ -24,7 +34,10 @@ import java.nio.charset.Charset
class PersonalizeFragment : Fragment() {
private val mainActivityVM: MainViewModel by activityViewModels()
private val viewModel: PersonalizeViewModel by viewModels { PersonalizeViewModelFactory(getPersonalizeJson()) }
private val personalizeVM: PersonalizeViewModel by viewModels { PersonalizeViewModelFactory(getPersonalizeJson()) }
private val paramsManager: ParamsManager by lazy { ParamsManagerFactory.createFactory().get(ActionType.Personalize)!! }
private val paramsVM: ParamsViewModel by viewModels() { ActionViewModelFactory(paramsManager) }
private val blockContainer: ViewGroup by lazy {
mainView.findViewById<LinearLayout>(R.id.ll_container)
@ -40,12 +53,24 @@ class PersonalizeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.ldBlockList.observe(viewLifecycleOwner, Observer { blocList ->
personalizeVM.ldBlockList.observe(viewLifecycleOwner, Observer { blocList ->
blocList.forEach { WidgetBuilder().build(it, blockContainer) }
})
mainActivityVM.ldDescriptionSwitch.observe(viewLifecycleOwner, Observer {
viewModel.toggleDescriptionVisibility(it)
personalizeVM.toggleDescriptionVisibility(it)
})
paramsVM.setCardManager(CardManager.init(requireActivity()))
paramsVM.ldResponse.observe(viewLifecycleOwner, Observer {
Log.d(this, "action response: ${if (it.length > 50) it.substring(0..50) else it}")
showSnackbarMessage(it)
})
paramsVM.seError.observe(viewLifecycleOwner, Observer { showSnackbarMessage(it) })
fab_action?.setOnClickListener { paramsVM.invokeMainAction() }
}
protected fun showSnackbarMessage(message: String) {
Snackbar.make(mainView, message, BaseTransientBottomBar.LENGTH_SHORT).show()
}
private fun getPersonalizeJson(): String {

View file

@ -34,5 +34,6 @@ enum class ActionType(@StringRes val resName: Int) {
ReadUserData(R.string.action_user_read_data),
WriteUserData(R.string.action_user_write_data),
Personalize(R.string.personalize),
Depersonalize(R.string.depersonalize),
Unknown(R.string.unknown),
}

View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_incoming_params_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
<include layout="@layout/w_action_response_json" />
</LinearLayout>
</ScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="@dimen/def_indent"
android:layout_marginBottom="@dimen/def_double_indent"
android:src="@drawable/ic_nfc" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1,14 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/ll_container"
<ScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/ll_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
android:layout_marginEnd="@dimen/def_indent"
android:layout_marginBottom="@dimen/def_double_indent"
android:src="@drawable/ic_nfc"
app:layout_anchor="@id/scroll_view"
app:layout_anchorGravity="bottom|end" />
</LinearLayout>
</ScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -111,6 +111,22 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_create_wallet" />
<Button
android:id="@+id/btn_personalize"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="Personalize"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_depersonalize"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="Depersonalize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View file

@ -43,6 +43,9 @@
<action
android:id="@+id/action_nav_entry_point_to_nav_personalize"
app:destination="@id/nav_personalize" />
<action
android:id="@+id/action_nav_entry_point_to_nav_depersonalize"
app:destination="@id/nav_depersonalize" />
</fragment>
@ -61,9 +64,15 @@
<fragment
android:id="@+id/nav_personalize"
android:name="com.tangem.tangemtest.card_use_cases.ui.personalize.PersonalizeFragment"
android:label="@string/action_issuer_read_data"
android:label="@string/action_personalize"
tools:layout="@layout/fg_personalize" />
<fragment
android:id="@+id/nav_depersonalize"
android:name="com.tangem.tangemtest.card_use_cases.ui.card.actions.DepesonalizeActionFragment"
android:label="@string/action_depersonalize"
tools:layout="@layout/fg_depersonalize" />
<fragment
android:id="@+id/nav_issuer_read_data"
android:name="com.tangem.tangemtest.card_use_cases.ui.IssuerReadDataActionFragment"

View file

@ -2,6 +2,7 @@
<resources>
<string name="personalize">Personalize</string>
<string name="depersonalize">Depersonalize</string>
<string name="pers_block_card_number">Card number</string>
<string name="pers_block_common">Common</string>
<string name="pers_block_signing_method">Signing method</string>

View file

@ -5,6 +5,7 @@
<string name="action_card_scan">Scan</string>
<string name="action_card_sign">Sign</string>
<string name="action_personalize">Personalize</string>
<string name="action_depersonalize">Depersonalize</string>
<string name="action_wallet_create">Create wallet</string>
<string name="action_wallet_purge">Purge wallet</string>
<string name="action_issuer_read_data">Read issuer data</string>