diff --git a/tangem-core/src/main/java/com/tangem/CardManager.kt b/tangem-core/src/main/java/com/tangem/CardManager.kt index dba3932cc3..ad9651f6b0 100644 --- a/tangem-core/src/main/java/com/tangem/CardManager.kt +++ b/tangem-core/src/main/java/com/tangem/CardManager.kt @@ -206,4 +206,6 @@ class CardManager( terminalKeys = terminalKeys ) } + + companion object } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt b/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt index 52f30a5e91..973ced5dd2 100644 --- a/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt +++ b/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt @@ -13,13 +13,13 @@ interface CardManagerDelegate { /** * It is called when user is expected to scan a Tangem Card with an Android device. */ - fun onNfcSessionStarted() + fun onNfcSessionStarted(cardId: String?) /** * It is called when security delay is triggered by the card. * A user is expected to hold the card until the security delay is over. */ - fun onSecurityDelay(ms: Int) + fun onSecurityDelay(ms: Int, totalDurationSeconds: Int) /** * It is called when user takes the card away from the Android device during the scanning diff --git a/tangem-core/src/main/java/com/tangem/tasks/Task.kt b/tangem-core/src/main/java/com/tangem/tasks/Task.kt index bbcf068f4e..e791190f9a 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/Task.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/Task.kt @@ -24,7 +24,7 @@ sealed class TaskError(description: String? = null) : Exception(description) { class Busy() : TaskError() class TagLost() : TaskError() - class ErrorProcessingCommand : TaskError() + class ErrorProcessingCommand(description: String? = null) : TaskError(description) class InvalidState : TaskError() class InsNotSupported : TaskError() class InvalidParams : TaskError() @@ -73,6 +73,7 @@ abstract class Task { var delegate: CardManagerDelegate? = null var reader: CardReader? = null var performPreflightRead: Boolean = true + var securityDelayDuration: Int = 0 /** * This method should be called to run the [Task] and perform all its operations. @@ -82,7 +83,7 @@ abstract class Task { */ fun run(cardEnvironment: CardEnvironment, callback: (result: TaskEvent) -> Unit) { - delegate?.onNfcSessionStarted() + delegate?.onNfcSessionStarted(cardEnvironment.cardId) reader?.openSession() Log.i(this::class.simpleName!!, "Nfc task is started") @@ -161,7 +162,7 @@ abstract class Task { StatusWord.NeedPause -> { // When NeedPause is returned from the card whenever security delay is triggered. val remainingTime = command.deserializeSecurityDelay(responseApdu, cardEnvironment) - if (remainingTime != null) delegate?.onSecurityDelay(remainingTime) + if (remainingTime != null) delegate?.onSecurityDelay(remainingTime, securityDelayDuration) Log.i(this::class.simpleName!!, "Nfc command ${command::class.simpleName!!} triggered security delay of $remainingTime milliseconds") sendRequest(command, commandApdu, cardEnvironment, callback) } diff --git a/tangem-demo/src/main/res/values/colors.xml b/tangem-demo/src/main/res/values/colors.xml index 69b22338c6..eb11907849 100644 --- a/tangem-demo/src/main/res/values/colors.xml +++ b/tangem-demo/src/main/res/values/colors.xml @@ -1,6 +1,6 @@ - #008577 - #00574B - #D81B60 + #027aff + #027AFF + #027AFF diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt index 8f37eb0c1c..d390b9ee99 100644 --- a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt @@ -1,12 +1,16 @@ package com.tangem.tangem_sdk_new +import android.animation.ObjectAnimator import android.view.View +import android.view.animation.DecelerateInterpolator import androidx.fragment.app.FragmentActivity import com.google.android.material.bottomsheet.BottomSheetDialog import com.tangem.CardManagerDelegate import com.tangem.Log import com.tangem.LoggerInterface import com.tangem.common.CompletionResult +import com.tangem.tangem_sdk_new.extensions.hide +import com.tangem.tangem_sdk_new.extensions.show import com.tangem.tangem_sdk_new.nfc.NfcReader import com.tangem.tangem_sdk_new.ui.NfcEnableDialog import com.tangem.tangem_sdk_new.ui.TouchCardAnimation @@ -28,13 +32,13 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel setLogger() } - override fun onNfcSessionStarted() { + override fun onNfcSessionStarted(cardId: String?) { reader.readingCancelled = false - postUI { showReadingDialog(activity) } + postUI { showReadingDialog(activity, cardId) } if (!reader.nfcEnabled) showNFCEnableDialog() } - private fun showReadingDialog(activity: FragmentActivity) { + private fun showReadingDialog(activity: FragmentActivity, cardId: String?) { val dialogView = activity.getLayoutInflater().inflate(R.layout.nfc_bottom_sheet, null) readingDialog = BottomSheetDialog(activity) readingDialog?.setContentView(dialogView) @@ -46,6 +50,11 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel activity, readingDialog!!.ivHandCardHorizontal, readingDialog!!.ivHandCardVertical, readingDialog!!.llHand, readingDialog!!.llNfc) nfcDeviceAntenna.init() + if (cardId != null) { + readingDialog?.tvCard?.visibility = View.VISIBLE + readingDialog?.tvCardId?.visibility = View.VISIBLE + readingDialog?.tvCardId?.text = cardId + } } readingDialog?.setOnCancelListener { reader.readingCancelled = true @@ -60,21 +69,36 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel activity.supportFragmentManager.let { nfcEnableDialog?.show(it, NfcEnableDialog.TAG) } } - override fun onSecurityDelay(ms: Int) { + override fun onSecurityDelay(ms: Int, totalDurationSeconds: Int) { postUI { - readingDialog?.lTouchCard?.visibility = View.GONE + readingDialog?.lTouchCard?.hide() readingDialog?.tvRemainingTime?.text = ms.div(100).toString() - readingDialog?.flSecurityDelay?.visibility = View.VISIBLE + readingDialog?.flSecurityDelay?.show() readingDialog?.tvTaskTitle?.text = activity.getText(R.string.dialog_security_delay) readingDialog?.tvTaskText?.text = activity.getText(R.string.dialog_security_delay_description) +// readingDialog?.pbSecurityDelay?.isIndeterminate = false + + if (readingDialog?.pbSecurityDelay?.max != totalDurationSeconds) { + readingDialog?.pbSecurityDelay?.max = totalDurationSeconds + } + readingDialog?.pbSecurityDelay?.progress = totalDurationSeconds - ms + 100 + + val animation = ObjectAnimator.ofInt( + readingDialog?.pbSecurityDelay, + "progress", + totalDurationSeconds - ms, + totalDurationSeconds - ms + 100) + animation.duration = 500 + animation.interpolator = DecelerateInterpolator() + animation.start() } } override fun onTagLost() { postUI { - readingDialog?.lTouchCard?.visibility = View.VISIBLE - readingDialog?.flSecurityDelay?.visibility = View.GONE + readingDialog?.lTouchCard?.show() + readingDialog?.flSecurityDelay?.hide() readingDialog?.tvTaskTitle?.text = activity.getText(R.string.dialog_ready_to_scan) readingDialog?.tvTaskText?.text = activity.getText(R.string.dialog_scan_text) } @@ -82,9 +106,9 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel override fun onNfcSessionCompleted() { postUI { - readingDialog?.lTouchCard?.visibility = View.GONE - readingDialog?.flSecurityDelay?.visibility = View.GONE - readingDialog?.flCompletion?.visibility = View.VISIBLE + readingDialog?.lTouchCard?.hide() + readingDialog?.flSecurityDelay?.hide() + readingDialog?.flCompletion?.show() readingDialog?.ivCompletion?.setImageDrawable(activity.getDrawable(R.drawable.ic_done_135dp)) } postUI(300) { readingDialog?.dismiss() } @@ -92,10 +116,10 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel override fun onError(error: TaskError?) { postUI { - readingDialog?.lTouchCard?.visibility = View.GONE - readingDialog?.flSecurityDelay?.visibility = View.GONE - readingDialog?.flCompletion?.visibility = View.VISIBLE - readingDialog?.ivCompletion?.setImageDrawable(activity.getDrawable(R.drawable.ic_error_outline_135dp)) + readingDialog?.lTouchCard?.hide() + readingDialog?.flSecurityDelay?.hide() + readingDialog?.flCompletion?.hide() + readingDialog?.flError?.show() readingDialog?.tvTaskTitle?.text = activity.getText(R.string.dialog_error) readingDialog?.tvTaskText?.text = if (error != null) error::class.simpleName else "" } diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/extensions/View.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/extensions/View.kt new file mode 100644 index 0000000000..008f194709 --- /dev/null +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/extensions/View.kt @@ -0,0 +1,11 @@ +package com.tangem.tangem_sdk_new.extensions + +import android.view.View + +internal fun View.show() { + this.visibility = View.VISIBLE +} + +internal fun View.hide() { + this.visibility = View.GONE +} \ No newline at end of file diff --git a/tangem-sdk/src/main/res/drawable/ic_error.xml b/tangem-sdk/src/main/res/drawable/ic_error.xml new file mode 100644 index 0000000000..d35c5b94ac --- /dev/null +++ b/tangem-sdk/src/main/res/drawable/ic_error.xml @@ -0,0 +1,6 @@ + + + + diff --git a/tangem-sdk/src/main/res/drawable/ic_nfc.xml b/tangem-sdk/src/main/res/drawable/ic_nfc.xml new file mode 100644 index 0000000000..c91a1240d6 --- /dev/null +++ b/tangem-sdk/src/main/res/drawable/ic_nfc.xml @@ -0,0 +1,10 @@ + + + diff --git a/tangem-sdk/src/main/res/drawable/pb_circle.xml b/tangem-sdk/src/main/res/drawable/pb_circle.xml new file mode 100644 index 0000000000..a3e74eb416 --- /dev/null +++ b/tangem-sdk/src/main/res/drawable/pb_circle.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tangem-sdk/src/main/res/layout/nfc_bottom_sheet.xml b/tangem-sdk/src/main/res/layout/nfc_bottom_sheet.xml index 496d0453bf..318e05a0d6 100644 --- a/tangem-sdk/src/main/res/layout/nfc_bottom_sheet.xml +++ b/tangem-sdk/src/main/res/layout/nfc_bottom_sheet.xml @@ -1,11 +1,60 @@ + + + + + + + + + + + + android:fontFamily="sans-serif-light" + android:textColor="@color/colorAccent" + android:textSize="60dp" + android:textStyle="normal" /> + style="?android:attr/progressBarStyleHorizontal" + android:layout_width="200dp" + android:layout_height="200dp" + android:layout_gravity="center" + android:indeterminate="false" + android:progressDrawable="@drawable/pb_circle" + android:secondaryProgress="100" /> @@ -55,8 +111,47 @@ android:id="@+id/ivCompletion" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:src="@drawable/ic_done_135dp" - android:layout_gravity="center"/> + android:layout_gravity="center" + android:src="@drawable/ic_done_135dp" /> + + + + + + + + + + diff --git a/tangem-sdk/src/main/res/values/strings.xml b/tangem-sdk/src/main/res/values/strings.xml index 1b84a3024b..aaabeff63d 100644 --- a/tangem-sdk/src/main/res/values/strings.xml +++ b/tangem-sdk/src/main/res/values/strings.xml @@ -8,5 +8,6 @@ Error Ready to Scan Scan card with your phone as shown above + Card