Updated on 2026-08-14
This commit is contained in:
parent
65274741d4
commit
f97cb52ae5
10 changed files with 78 additions and 37 deletions
|
|
@ -19,6 +19,8 @@ import com.tangem.crypto.pbkdf2Hash
|
|||
*/
|
||||
interface CardSessionRunnable<T : CommandResponse> {
|
||||
|
||||
val performPreflightRead: Boolean
|
||||
|
||||
/**
|
||||
* The starting point for custom business logic.
|
||||
* Implement this interface and use [TangemSdk.startSessionWithRunnable] to run.
|
||||
|
|
@ -55,6 +57,8 @@ class CardSession(
|
|||
*/
|
||||
private var isBusy = false
|
||||
|
||||
private var performPreflightRead = true
|
||||
|
||||
/**
|
||||
* This metod starts a card session, performs preflight [ReadCommand],
|
||||
* invokes [CardSessionRunnable.run] and closes the session.
|
||||
|
|
@ -64,6 +68,8 @@ class CardSession(
|
|||
fun <T : CardSessionRunnable<R>, R : CommandResponse> startWithRunnable(
|
||||
runnable: T, callback: (result: CompletionResult<R>) -> Unit) {
|
||||
|
||||
performPreflightRead = runnable.performPreflightRead
|
||||
|
||||
start { session, error ->
|
||||
if (error != null) {
|
||||
callback(CompletionResult.Failure(error))
|
||||
|
|
@ -104,6 +110,11 @@ class CardSession(
|
|||
callback(this, error)
|
||||
}
|
||||
|
||||
if (!performPreflightRead) {
|
||||
callback(this, null)
|
||||
return
|
||||
}
|
||||
|
||||
preflightRead() { result ->
|
||||
when (result) {
|
||||
is CompletionResult.Failure -> {
|
||||
|
|
|
|||
|
|
@ -307,7 +307,7 @@ class TangemSdk(
|
|||
* card response in the form of [DepersonalizeResponse] if the task was performed successfully
|
||||
* or [TangemSdkError] in case of an error.
|
||||
* */
|
||||
fun depersonalize(cardId: String, initialMessage: Message? = null,
|
||||
fun depersonalize(cardId: String? = null, initialMessage: Message? = null,
|
||||
callback: (result: CompletionResult<DepersonalizeResponse>) -> Unit) {
|
||||
startSessionWithRunnable(DepersonalizeCommand(), cardId, initialMessage, callback)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ interface CommandResponse
|
|||
*/
|
||||
abstract class Command<T : CommandResponse> : CardSessionRunnable<T> {
|
||||
|
||||
override val performPreflightRead: Boolean = true
|
||||
|
||||
/**
|
||||
* Serializes data into an array of [com.tangem.common.tlv.Tlv],
|
||||
* then creates [CommandApdu] with this data.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
package com.tangem.commands.personalization
|
||||
|
||||
import com.tangem.CardSession
|
||||
import com.tangem.SessionEnvironment
|
||||
import com.tangem.TangemSdkError
|
||||
import com.tangem.commands.CardStatus
|
||||
import com.tangem.commands.Command
|
||||
import com.tangem.commands.CommandResponse
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.apdu.CommandApdu
|
||||
import com.tangem.common.apdu.Instruction
|
||||
import com.tangem.common.apdu.ResponseApdu
|
||||
|
|
@ -21,17 +17,19 @@ data class DepersonalizeResponse(val success: Boolean) : CommandResponse
|
|||
*/
|
||||
class DepersonalizeCommand : Command<DepersonalizeResponse>() {
|
||||
|
||||
override fun performPreCheck(session: CardSession, callback: (result: CompletionResult<DepersonalizeResponse>) -> Unit): Boolean {
|
||||
if (session.environment.card?.status == CardStatus.NotPersonalized) {
|
||||
callback(CompletionResult.Failure(TangemSdkError.NotPersonalized()))
|
||||
return true
|
||||
}
|
||||
if (session.environment.card?.firmwareVersion?.contains("SDK") == false) {
|
||||
callback(CompletionResult.Failure(TangemSdkError.CannotBeDepersonalized()))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
override val performPreflightRead = false
|
||||
|
||||
// override fun performPreCheck(session: CardSession, callback: (result: CompletionResult<DepersonalizeResponse>) -> Unit): Boolean {
|
||||
// if (session.environment.card?.status == CardStatus.NotPersonalized) {
|
||||
// callback(CompletionResult.Failure(TangemSdkError.NotPersonalized()))
|
||||
// return true
|
||||
// }
|
||||
// if (session.environment.card?.firmwareVersion?.contains("SDK") == false) {
|
||||
// callback(CompletionResult.Failure(TangemSdkError.CannotBeDepersonalized()))
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
|
||||
override fun serialize(environment: SessionEnvironment): CommandApdu {
|
||||
return CommandApdu(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import com.tangem.common.CompletionResult
|
|||
|
||||
class CreateWalletTask : CardSessionRunnable<CreateWalletResponse> {
|
||||
|
||||
override val performPreflightRead = true
|
||||
|
||||
override fun run(session: CardSession, callback: (result: CompletionResult<CreateWalletResponse>) -> Unit) {
|
||||
val curve = session.environment.card?.curve
|
||||
if (curve == null) {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import com.tangem.common.CompletionResult
|
|||
*/
|
||||
internal class ScanTask : CardSessionRunnable<Card> {
|
||||
|
||||
override val performPreflightRead = true
|
||||
|
||||
override fun run(session: CardSession, callback: (result: CompletionResult<Card>) -> Unit) {
|
||||
|
||||
val card = session.environment.card
|
||||
|
|
|
|||
|
|
@ -1,26 +1,14 @@
|
|||
package com.tangem.devkit.ucase.domain.actions
|
||||
|
||||
import com.tangem.devkit._arch.structure.Id
|
||||
import com.tangem.devkit._arch.structure.PayloadHolder
|
||||
import com.tangem.devkit._arch.structure.abstraction.findItem
|
||||
import com.tangem.devkit.ucase.domain.paramsManager.ActionCallback
|
||||
import com.tangem.devkit.ucase.variants.TlvId
|
||||
import com.tangem.devkit.ucase.domain.paramsManager.triggers.afterAction.AfterScanModifier
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class DepersonalizeAction : BaseAction() {
|
||||
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
|
||||
val item = attrs.itemList.findItem(TlvId.CardId) ?: return
|
||||
val cardId = item.viewModel.data as? String ?: return
|
||||
|
||||
attrs.tangemSdk.depersonalize(cardId) { handleResult(payload, it, null, attrs, callback) }
|
||||
}
|
||||
|
||||
override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? {
|
||||
return when (id) {
|
||||
TlvId.CardId -> { callback -> ScanAction().executeMainAction(payload, attrs, callback) }
|
||||
else -> null
|
||||
}
|
||||
attrs.tangemSdk.depersonalize { handleResult(payload, it, AfterScanModifier(), attrs, callback) }
|
||||
}
|
||||
}
|
||||
|
|
@ -10,13 +10,7 @@ import com.tangem.devkit.ucase.variants.TlvId
|
|||
*/
|
||||
class ScanItemsManager : BaseItemsManager(ScanAction())
|
||||
|
||||
class DepersonalizeItemsManager : BaseItemsManager(DepersonalizeAction()) {
|
||||
|
||||
init {
|
||||
setItemChangeConsequences(CardIdConsequence())
|
||||
setItems(listOf(EditTextItem(TlvId.CardId, null)))
|
||||
}
|
||||
}
|
||||
class DepersonalizeItemsManager : BaseItemsManager(DepersonalizeAction())
|
||||
|
||||
class SignItemsManager : BaseItemsManager(SignAction()) {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,18 @@
|
|||
package com.tangem.devkit.ucase.variants.depersonalize.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import com.tangem.commands.Card
|
||||
import com.tangem.devkit.R
|
||||
import com.tangem.devkit.ucase.domain.paramsManager.ItemsManager
|
||||
import com.tangem.devkit.ucase.domain.paramsManager.managers.DepersonalizeItemsManager
|
||||
import com.tangem.devkit.ucase.ui.BaseCardActionFragment
|
||||
import com.tangem.devkit.ucase.variants.responses.ui.ResponseFragment
|
||||
import ru.dev.gbixahue.eu4d.lib.android._android.views.dpToPx
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -10,4 +20,37 @@ import com.tangem.devkit.ucase.ui.BaseCardActionFragment
|
|||
class DepersonalizeActionFragment : BaseCardActionFragment() {
|
||||
|
||||
override val itemsManager: ItemsManager by lazy { DepersonalizeItemsManager() }
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val howToUseView = createHowToUse()
|
||||
contentContainer.layoutParams = FrameLayout.LayoutParams(-1, -1, Gravity.CENTER)
|
||||
contentContainer.addView(howToUseView)
|
||||
}
|
||||
|
||||
private fun createHowToUse(): View {
|
||||
val fl = FrameLayout(requireContext())
|
||||
fl.layoutParams = FrameLayout.LayoutParams(-1, -1, Gravity.CENTER)
|
||||
val tv = TextView(requireContext()).apply {
|
||||
val padding = dpToPx(16f).toInt()
|
||||
setPadding(padding, 0, padding, 0)
|
||||
gravity = Gravity.CENTER
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
|
||||
setText(R.string.htu_depersonalize_action)
|
||||
}
|
||||
fl.addView(tv)
|
||||
return fl
|
||||
}
|
||||
|
||||
override fun initViews() {
|
||||
swrLayout.isEnabled = false
|
||||
actionFab.setOnClickListener { actionVM.invokeMainAction() }
|
||||
}
|
||||
|
||||
override fun handleResponseCardData(card: Card) {
|
||||
super.handleResponseCardData(card)
|
||||
val bundle = ResponseFragment.setTittle(R.string.fg_name_response_depersonalization)
|
||||
navigateTo(R.id.action_nav_card_action_to_response_screen, bundle, null)
|
||||
}
|
||||
}
|
||||
|
|
@ -30,5 +30,6 @@
|
|||
<string name="info_action_user_write_data"> This command writes to the card User Data and User Counter fields.</string>
|
||||
<string name="info_action_user_write_protected_data"> This command writes to the card User Protected Data and User Protected Counter fields.</string>
|
||||
|
||||
<string name="htu_depersonalize_action">To depersonalize the card, press the button at the right bottom corner of the screen</string>
|
||||
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue