789 lines
No EOL
33 KiB
Kotlin
789 lines
No EOL
33 KiB
Kotlin
package com.tangem.presentation.fragment
|
|
|
|
import android.app.Activity
|
|
import android.app.AlertDialog
|
|
import android.content.*
|
|
import android.content.Context.CLIPBOARD_SERVICE
|
|
import android.content.pm.PackageManager
|
|
import android.content.res.ColorStateList
|
|
import android.nfc.NfcAdapter
|
|
import android.nfc.Tag
|
|
import android.nfc.tech.IsoDep
|
|
import android.os.Bundle
|
|
import android.support.v4.app.Fragment
|
|
import android.support.v4.content.ContextCompat
|
|
import android.text.Html
|
|
import android.util.Log
|
|
import android.view.Gravity
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import android.view.ViewGroup
|
|
import android.widget.Toast
|
|
import com.tangem.App
|
|
import com.tangem.Constant
|
|
import com.tangem.data.Blockchain
|
|
import com.tangem.data.network.ServerApiCommon
|
|
import com.tangem.domain.wallet.BalanceValidator
|
|
import com.tangem.domain.wallet.CoinEngine
|
|
import com.tangem.domain.wallet.CoinEngineFactory
|
|
import com.tangem.domain.wallet.TangemContext
|
|
import com.tangem.presentation.activity.*
|
|
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
|
|
import com.tangem.presentation.dialog.PINSwapWarningDialog
|
|
import com.tangem.presentation.dialog.ShowQRCodeDialog
|
|
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
|
import com.tangem.tangemcard.android.reader.NfcManager
|
|
import com.tangem.tangemcard.android.reader.NfcReader
|
|
import com.tangem.tangemcard.data.EXTRA_TANGEM_CARD
|
|
import com.tangem.tangemcard.data.EXTRA_TANGEM_CARD_UID
|
|
import com.tangem.tangemcard.data.TangemCard
|
|
import com.tangem.tangemcard.data.loadFromBundle
|
|
import com.tangem.tangemcard.reader.CardProtocol
|
|
import com.tangem.tangemcard.tasks.VerifyCardTask
|
|
import com.tangem.tangemcard.util.Util
|
|
import com.tangem.tangemserver.android.ServerApiTangem
|
|
import com.tangem.tangemserver.android.model.CardVerifyAndGetInfo
|
|
import com.tangem.util.UtilHelper
|
|
import com.tangem.wallet.R
|
|
import kotlinx.android.synthetic.main.fr_loaded_wallet.*
|
|
import java.io.InputStream
|
|
import java.util.*
|
|
|
|
class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notifications, SharedPreferences.OnSharedPreferenceChangeListener {
|
|
companion object {
|
|
val TAG: String = LoadedWallet::class.java.simpleName
|
|
}
|
|
|
|
private lateinit var nfcManager: NfcManager
|
|
|
|
private var serverApiCommon: ServerApiCommon = ServerApiCommon()
|
|
private var serverApiTangem: ServerApiTangem = ServerApiTangem()
|
|
|
|
private var singleToast: Toast? = null
|
|
private lateinit var ctx: TangemContext
|
|
|
|
private var lastTag: Tag? = null
|
|
private var lastReadSuccess = true
|
|
private var verifyCardTask: VerifyCardTask? = null
|
|
private var requestPIN2Count = 0
|
|
private var timerHideErrorAndMessage: Timer? = null
|
|
private var newPIN = ""
|
|
private var newPIN2 = ""
|
|
private var cardProtocol: CardProtocol? = null
|
|
private val inactiveColor: ColorStateList by lazy { resources.getColorStateList(R.color.btn_dark) }
|
|
private val activeColor: ColorStateList by lazy { resources.getColorStateList(R.color.colorAccent) }
|
|
private var requestCounter: Int = 0
|
|
set(value)
|
|
{
|
|
field=value
|
|
Log.i(TAG, "requestCounter, set $field")
|
|
if (field <= 0 && srl!=null && srl.isRefreshing ) {
|
|
Log.e(TAG, "+++++++++++ FINISH REFRESH")
|
|
if (srl != null) srl!!.isRefreshing = false
|
|
//updateViews()
|
|
}
|
|
}
|
|
private var timerRepeatRefresh: Timer? = null
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
nfcManager = NfcManager(activity, this)
|
|
|
|
ctx = TangemContext.loadFromBundle(activity, activity?.intent?.extras)
|
|
|
|
lastTag = activity?.intent?.getParcelableExtra(Constant.EXTRA_LAST_DISCOVERED_TAG)
|
|
}
|
|
|
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
return inflater.inflate(R.layout.fr_loaded_wallet, container, false)
|
|
}
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
super.onViewCreated(view, savedInstanceState)
|
|
|
|
if (ctx.blockchain == Blockchain.Token)
|
|
tvBalance.setSingleLine(false)
|
|
|
|
ivTangemCard.setImageBitmap(App.localStorage.getCardArtworkBitmap(ctx.card))
|
|
|
|
btnExtract.isEnabled = false
|
|
btnExtract.backgroundTintList = inactiveColor
|
|
|
|
tvWallet.text = ctx.coinData.wallet
|
|
|
|
// set listeners
|
|
srl.setOnRefreshListener { refresh() }
|
|
btnLookup.setOnClickListener {
|
|
val engine = CoinEngineFactory.create(ctx)
|
|
val browserIntent = Intent(Intent.ACTION_VIEW, engine?.shareWalletUriExplorer)
|
|
startActivity(browserIntent)
|
|
}
|
|
btnCopy.setOnClickListener { doShareWallet(false) }
|
|
tvWallet.setOnClickListener { doShareWallet(false) }
|
|
btnLoad.setOnClickListener {
|
|
//if (BuildConfig.DEBUG) {
|
|
if (true) {
|
|
val items = arrayOf<CharSequence>(getString(R.string.in_app), getString(R.string.load_via_share_address), getString(R.string.load_via_qr))//, getString(R.string.via_cryptonit), getString(R.string.via_kraken))
|
|
val cw = android.view.ContextThemeWrapper(activity, R.style.AlertDialogTheme)
|
|
val dialog = AlertDialog.Builder(cw).setItems(items
|
|
) { _, which ->
|
|
when (items[which]) {
|
|
getString(R.string.in_app) -> {
|
|
try {
|
|
val engine = CoinEngineFactory.create(ctx)
|
|
val intent = Intent(Intent.ACTION_VIEW, engine!!.shareWalletUri)
|
|
intent.addCategory(Intent.CATEGORY_DEFAULT)
|
|
startActivity(intent)
|
|
} catch (e: ActivityNotFoundException) {
|
|
showSingleToast(R.string.no_compatible_wallet)
|
|
}
|
|
}
|
|
getString(R.string.load_via_share_address) -> {
|
|
doShareWallet(true)
|
|
}
|
|
getString(R.string.load_via_qr) -> {
|
|
val engine = CoinEngineFactory.create(ctx)
|
|
ShowQRCodeDialog.show(activity, engine!!.shareWalletUri.toString())
|
|
}
|
|
// getString(R.string.via_cryptonit2) -> {
|
|
// val intent = Intent(ctx, PrepareCryptonitOtherApiWithdrawalActivity::class.java)
|
|
// intent.putExtra("UID", card!!.uid)
|
|
// intent.putExtra("Card", card!!.asBundle)
|
|
// startActivityForResult(intent, REQUEST_CODE_RECEIVE_PAYMENT)
|
|
// }
|
|
getString(R.string.via_cryptonit) -> {
|
|
val intent = Intent(activity, PrepareCryptonitWithdrawalActivity::class.java)
|
|
ctx.saveToIntent(intent)
|
|
startActivityForResult(intent, Constant.REQUEST_CODE_RECEIVE_PAYMENT)
|
|
}
|
|
getString(R.string.via_kraken) -> {
|
|
val intent = Intent(activity, PrepareKrakenWithdrawalActivity::class.java)
|
|
ctx.saveToIntent(intent)
|
|
startActivityForResult(intent, Constant.REQUEST_CODE_RECEIVE_PAYMENT)
|
|
}
|
|
else -> {
|
|
}
|
|
}
|
|
}
|
|
val dlg = dialog.show()
|
|
val wlp = dlg.window.attributes
|
|
wlp.gravity = Gravity.BOTTOM
|
|
dlg.window.attributes = wlp
|
|
} else {
|
|
try {
|
|
val engine = CoinEngineFactory.create(ctx)
|
|
val intent = Intent(Intent.ACTION_VIEW, engine!!.shareWalletUri)
|
|
intent.addCategory(Intent.CATEGORY_DEFAULT)
|
|
startActivity(intent)
|
|
} catch (e: ActivityNotFoundException) {
|
|
showSingleToast(R.string.no_compatible_wallet)
|
|
}
|
|
}
|
|
}
|
|
btnDetails.setOnClickListener {
|
|
if (cardProtocol != null)
|
|
// openVerifyCard(cardProtocol!!)
|
|
(activity as LoadedWalletActivity).navigator.showVerifyCard(context as Activity, ctx)
|
|
else
|
|
showSingleToast(R.string.need_attach_card_again)
|
|
}
|
|
btnScanAgain.setOnClickListener { (activity as LoadedWalletActivity).navigator.showMain(context as Activity) }
|
|
btnExtract.setOnClickListener {
|
|
val engine = CoinEngineFactory.create(ctx)
|
|
if (UtilHelper.isOnline(context as Activity)) {
|
|
if (!engine!!.isExtractPossible)
|
|
showSingleToast(ctx.message)
|
|
else if (ctx.card!!.remainingSignatures == 0)
|
|
showSingleToast(R.string.card_has_no_remaining_signature)
|
|
else {
|
|
val intent = Intent(activity, PreparePaymentActivity::class.java)
|
|
ctx.saveToIntent(intent)
|
|
startActivityForResult(intent, Constant.REQUEST_CODE_SEND_PAYMENT)
|
|
}
|
|
} else
|
|
Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
|
|
}
|
|
|
|
// request card verify and get info listener
|
|
val cardVerifyAndGetInfoListener: ServerApiTangem.CardVerifyAndGetInfoListener = object : ServerApiTangem.CardVerifyAndGetInfoListener {
|
|
override fun onSuccess(cardVerifyAndGetArtworkResponse: CardVerifyAndGetInfo.Response?) {
|
|
Log.i(TAG,"cardVerifyAndGetInfoListener onSuccess")
|
|
if( activity==null || !UtilHelper.isOnline(activity!!)) return
|
|
|
|
val result = cardVerifyAndGetArtworkResponse?.results!![0]
|
|
if (result.error != null) {
|
|
ctx.card!!.isOnlineVerified = false
|
|
return
|
|
}
|
|
ctx.card!!.isOnlineVerified = result.passed
|
|
|
|
|
|
requestCounter--
|
|
// if (requestCounter == 0)
|
|
updateViews()
|
|
|
|
if (!result.passed) return
|
|
|
|
if (App.localStorage.checkBatchInfoChanged(ctx.card!!, result)) {
|
|
Log.w(TAG, "Batch ${result.batch} info changed to '$result'")
|
|
ivTangemCard.setImageBitmap(App.localStorage.getCardArtworkBitmap(ctx.card!!))
|
|
App.localStorage.applySubstitution(ctx.card!!)
|
|
refresh()
|
|
}
|
|
if (result.artwork != null && App.localStorage.checkNeedUpdateArtwork(result.artwork)) {
|
|
Log.w(TAG, "Artwork '${result.artwork!!.id}' updated, need download")
|
|
requestCounter++
|
|
serverApiTangem.requestArtwork(result.artwork!!.id, result.artwork!!.getUpdateDate(), ctx.card!!)
|
|
updateViews()
|
|
}
|
|
// Log.i(TAG, "setCardVerify " + it.results!![0].passed)
|
|
}
|
|
|
|
override fun onFail(message: String?) {
|
|
Log.i(TAG,"cardVerifyAndGetInfoListener onFail")
|
|
if( activity==null || !UtilHelper.isOnline(activity!!)) return
|
|
requestCounter--
|
|
updateViews()
|
|
}
|
|
}
|
|
serverApiTangem.setCardVerifyAndGetInfoListener(cardVerifyAndGetInfoListener)
|
|
|
|
// request artwork listener
|
|
val artworkListener: ServerApiTangem.ArtworkListener = object : ServerApiTangem.ArtworkListener {
|
|
override fun onSuccess(artworkId: String?, inputStream: InputStream?, updateDate: Date?) {
|
|
Log.i(TAG,"artworkListener onSuccess")
|
|
if( activity==null || !UtilHelper.isOnline(activity!!)) return
|
|
App.localStorage.updateArtwork(artworkId!!, inputStream!!, updateDate!!)
|
|
requestCounter--
|
|
ivTangemCard.setImageBitmap(App.localStorage.getCardArtworkBitmap(ctx.card!!))
|
|
updateViews()
|
|
}
|
|
|
|
override fun onFail(message: String?) {
|
|
Log.i(TAG,"artworkListener onFail")
|
|
if( activity==null || !UtilHelper.isOnline(activity!!)) return
|
|
requestCounter--
|
|
updateViews()
|
|
}
|
|
}
|
|
serverApiTangem.setArtworkListener(artworkListener)
|
|
|
|
// request rate info listener
|
|
serverApiCommon.setRateInfoData {
|
|
if( activity==null || !UtilHelper.isOnline(activity!!)) return@setRateInfoData
|
|
val rate = it.priceUsd.toFloat()
|
|
ctx.coinData!!.rate = rate
|
|
ctx.coinData!!.rateAlter = rate
|
|
}
|
|
|
|
refresh()
|
|
|
|
startVerify(lastTag)
|
|
}
|
|
|
|
override fun onResume() {
|
|
super.onResume()
|
|
nfcManager.onResume()
|
|
}
|
|
|
|
override fun onPause() {
|
|
super.onPause()
|
|
nfcManager.onPause()
|
|
if (timerRepeatRefresh != null)
|
|
timerRepeatRefresh!!.cancel()
|
|
}
|
|
|
|
override fun onStop() {
|
|
super.onStop()
|
|
nfcManager.onStop()
|
|
}
|
|
|
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
var data = data
|
|
super.onActivityResult(requestCode, resultCode, data)
|
|
when (requestCode) {
|
|
Constant.REQUEST_CODE_VERIFY_CARD ->
|
|
// action when erase wallet
|
|
if (resultCode == Activity.RESULT_OK) {
|
|
if (activity != null)
|
|
activity?.finish()
|
|
}
|
|
|
|
Constant.REQUEST_CODE_ENTER_NEW_PIN -> if (resultCode == Activity.RESULT_OK) {
|
|
if (data != null) {
|
|
if (data.extras != null && data.extras!!.containsKey("confirmPIN")) {
|
|
val intent = Intent(activity, PinRequestActivity::class.java)
|
|
intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString())
|
|
ctx.saveToIntent(intent)
|
|
newPIN = data.getStringExtra("newPIN")
|
|
startActivityForResult(intent, Constant.REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN)
|
|
} else {
|
|
val intent = Intent(activity, PinRequestActivity::class.java)
|
|
intent.putExtra("newPIN", data.getStringExtra("newPIN"))
|
|
intent.putExtra("mode", PinRequestActivity.Mode.ConfirmNewPIN.toString())
|
|
startActivityForResult(intent, Constant.REQUEST_CODE_ENTER_NEW_PIN)
|
|
}
|
|
}
|
|
}
|
|
Constant.REQUEST_CODE_ENTER_NEW_PIN2 -> if (resultCode == Activity.RESULT_OK) {
|
|
if (data != null) {
|
|
if (data.extras != null && data.extras!!.containsKey("confirmPIN2")) {
|
|
val intent = Intent(activity, PinRequestActivity::class.java)
|
|
intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString())
|
|
ctx.saveToIntent(intent)
|
|
newPIN2 = data.getStringExtra("newPIN2")
|
|
startActivityForResult(intent, Constant.REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN)
|
|
} else {
|
|
val intent = Intent(activity, PinRequestActivity::class.java)
|
|
intent.putExtra("newPIN2", data.getStringExtra("newPIN2"))
|
|
intent.putExtra("mode", PinRequestActivity.Mode.ConfirmNewPIN2.toString())
|
|
startActivityForResult(intent, Constant.REQUEST_CODE_ENTER_NEW_PIN2)
|
|
}
|
|
}
|
|
}
|
|
Constant.REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN -> if (resultCode == Activity.RESULT_OK) {
|
|
if (newPIN == "")
|
|
newPIN = ctx.card!!.pin
|
|
|
|
if (newPIN2 == "")
|
|
newPIN2 = App.pinStorage.piN2
|
|
|
|
val pinSwapWarningDialog = PINSwapWarningDialog()
|
|
pinSwapWarningDialog.setOnRefreshPage { (activity as LoadedWalletActivity).navigator.showPinSwap(context as Activity, newPIN, newPIN2) }
|
|
val bundle = Bundle()
|
|
if (!CardProtocol.isDefaultPIN(newPIN) || !CardProtocol.isDefaultPIN2(newPIN2))
|
|
bundle.putString(PINSwapWarningDialog.EXTRA_MESSAGE, getString(R.string.if_you_forget))
|
|
else
|
|
bundle.putString(PINSwapWarningDialog.EXTRA_MESSAGE, getString(R.string.if_you_use_default))
|
|
pinSwapWarningDialog.arguments = bundle
|
|
pinSwapWarningDialog.show(activity?.supportFragmentManager, PINSwapWarningDialog.TAG)
|
|
}
|
|
|
|
Constant.REQUEST_CODE_SWAP_PIN -> if (resultCode == Activity.RESULT_OK) {
|
|
if (data == null) {
|
|
data = Intent()
|
|
ctx.saveToIntent(data)
|
|
data.putExtra(Constant.EXTRA_MODIFICATION, "delete")
|
|
} else
|
|
data.putExtra(Constant.EXTRA_MODIFICATION, "update")
|
|
|
|
activity?.setResult(Activity.RESULT_OK, data)
|
|
activity?.finish()
|
|
|
|
} else {
|
|
if (data != null && data.extras != null && data.extras!!.containsKey(EXTRA_TANGEM_CARD_UID) && data.extras!!.containsKey(EXTRA_TANGEM_CARD)) {
|
|
val updatedCard = TangemCard(data.getStringExtra(EXTRA_TANGEM_CARD_UID))
|
|
updatedCard.loadFromBundle(data.getBundleExtra(EXTRA_TANGEM_CARD))
|
|
ctx.card = updatedCard
|
|
}
|
|
if (resultCode == CreateNewWalletActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) {
|
|
requestPIN2Count++
|
|
val intent = Intent(activity, PinRequestActivity::class.java)
|
|
intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString())
|
|
ctx.saveToIntent(intent)
|
|
startActivityForResult(intent, Constant.REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN)
|
|
return
|
|
} else {
|
|
if (data != null && data.extras!!.containsKey("message")) {
|
|
ctx.error = data.getStringExtra("message")
|
|
}
|
|
}
|
|
}
|
|
Constant.REQUEST_CODE_REQUEST_PIN2_FOR_PURGE -> if (resultCode == Activity.RESULT_OK) {
|
|
val intent = Intent(activity, PurgeActivity::class.java)
|
|
ctx.saveToIntent(intent)
|
|
startActivityForResult(intent, Constant.REQUEST_CODE_PURGE)
|
|
}
|
|
Constant.REQUEST_CODE_PURGE -> if (resultCode == Activity.RESULT_OK) {
|
|
if (data == null) {
|
|
data = Intent()
|
|
ctx.saveToIntent(data)
|
|
data.putExtra(Constant.EXTRA_MODIFICATION, "delete")
|
|
} else {
|
|
data.putExtra(Constant.EXTRA_MODIFICATION, "update")
|
|
}
|
|
|
|
activity?.setResult(Activity.RESULT_OK, data)
|
|
activity?.finish()
|
|
|
|
} else {
|
|
if (data != null && data.extras != null && data.extras!!.containsKey(EXTRA_TANGEM_CARD_UID) && data.extras!!.containsKey(EXTRA_TANGEM_CARD)) {
|
|
val updatedCard = TangemCard(data.getStringExtra(EXTRA_TANGEM_CARD_UID))
|
|
updatedCard.loadFromBundle(data.getBundleExtra(EXTRA_TANGEM_CARD))
|
|
ctx.card = updatedCard
|
|
}
|
|
if (resultCode == CreateNewWalletActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) {
|
|
requestPIN2Count++
|
|
val intent = Intent(activity, PinRequestActivity::class.java)
|
|
intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString())
|
|
ctx.saveToIntent(intent)
|
|
startActivityForResult(intent, Constant.REQUEST_CODE_REQUEST_PIN2_FOR_PURGE)
|
|
return
|
|
} else {
|
|
if (data != null && data.extras!!.containsKey("message")) {
|
|
ctx.error = data.getStringExtra("message")
|
|
}
|
|
}
|
|
updateViews()
|
|
}
|
|
Constant.REQUEST_CODE_SEND_PAYMENT, Constant.REQUEST_CODE_RECEIVE_PAYMENT -> {
|
|
if (resultCode == Activity.RESULT_OK) {
|
|
ctx.coinData?.clearInfo()
|
|
srl?.postDelayed({ this.refresh() }, 5000)
|
|
srl?.isRefreshing = true
|
|
updateViews()
|
|
}
|
|
|
|
if (data != null && data.extras != null) {
|
|
if (data.extras!!.containsKey(EXTRA_TANGEM_CARD_UID) && data.extras!!.containsKey(EXTRA_TANGEM_CARD)) {
|
|
val updatedCard = TangemCard(data.getStringExtra(EXTRA_TANGEM_CARD_UID))
|
|
updatedCard.loadFromBundle(data.getBundleExtra(EXTRA_TANGEM_CARD))
|
|
ctx.card = updatedCard
|
|
}
|
|
if (data.extras!!.containsKey("message")) {
|
|
if (resultCode == Activity.RESULT_OK) {
|
|
ctx.message = data.getStringExtra("message")
|
|
} else {
|
|
ctx.error = data.getStringExtra("message")
|
|
}
|
|
}
|
|
updateViews()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun onTagDiscovered(tag: Tag) {
|
|
startVerify(tag)
|
|
}
|
|
|
|
override fun onReadStart(cardProtocol: CardProtocol) {
|
|
if (rlProgressBar != null)
|
|
rlProgressBar.post { rlProgressBar.visibility = View.VISIBLE }
|
|
}
|
|
|
|
override fun onReadProgress(protocol: CardProtocol, progress: Int) {
|
|
|
|
}
|
|
|
|
override fun onReadFinish(cardProtocol: CardProtocol?) {
|
|
verifyCardTask = null
|
|
|
|
if (cardProtocol != null) {
|
|
if (cardProtocol.error == null) {
|
|
|
|
rlProgressBar?.post {
|
|
rlProgressBar?.visibility = View.GONE
|
|
this.cardProtocol = cardProtocol
|
|
if (!cardProtocol.card.isWalletPublicKeyValid) refresh()
|
|
else updateViews()
|
|
}
|
|
} else {
|
|
// remove last UIDs because of error and no card read
|
|
rlProgressBar?.post {
|
|
lastReadSuccess = false
|
|
if (cardProtocol.error is CardProtocol.TangemException_ExtendedLengthNotSupported)
|
|
if (!NoExtendedLengthSupportDialog.allReadyShowed)
|
|
NoExtendedLengthSupportDialog().show(activity?.supportFragmentManager, NoExtendedLengthSupportDialog.TAG)
|
|
else
|
|
Toast.makeText(activity, R.string.try_to_scan_again, Toast.LENGTH_SHORT).show()
|
|
}
|
|
}
|
|
}
|
|
|
|
rlProgressBar?.postDelayed({
|
|
try {
|
|
rlProgressBar?.visibility = View.GONE
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
}
|
|
}, 500)
|
|
}
|
|
|
|
override fun onReadCancel() {
|
|
verifyCardTask = null
|
|
rlProgressBar?.postDelayed({
|
|
try {
|
|
rlProgressBar?.visibility = View.GONE
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
}
|
|
}, 500)
|
|
}
|
|
|
|
override fun onReadWait(msec: Int) {
|
|
WaitSecurityDelayDialog.OnReadWait(activity, msec)
|
|
}
|
|
|
|
override fun onReadBeforeRequest(timeout: Int) {
|
|
WaitSecurityDelayDialog.onReadBeforeRequest(activity, timeout)
|
|
}
|
|
|
|
override fun onReadAfterRequest() {
|
|
WaitSecurityDelayDialog.onReadAfterRequest(activity)
|
|
}
|
|
|
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
|
|
|
}
|
|
|
|
fun updateViews() {
|
|
if( activity==null || !UtilHelper.isOnline(activity!!)) return
|
|
|
|
if (timerHideErrorAndMessage != null) {
|
|
timerHideErrorAndMessage!!.cancel()
|
|
timerHideErrorAndMessage = null
|
|
}
|
|
|
|
if (ctx.hasError()) {
|
|
tvError.visibility = View.VISIBLE
|
|
tvError.text = ctx.error
|
|
} else {
|
|
tvError.visibility = View.GONE
|
|
tvError.text = ""
|
|
}
|
|
|
|
if (ctx.message == null || ctx.message.isEmpty()) {
|
|
tvMessage.text = ""
|
|
tvMessage.visibility = View.GONE
|
|
} else {
|
|
tvMessage.text = ctx.message
|
|
tvMessage.visibility = View.VISIBLE
|
|
}
|
|
|
|
if (srl!!.isRefreshing) {
|
|
tvBalanceLine1.setTextColor(resources.getColor(R.color.primary))
|
|
tvBalanceLine1.text = getString(R.string.verifying_in_blockchain)
|
|
tvBalanceLine2.text = ""
|
|
tvBalance.text = ""
|
|
tvBalanceEquivalent.text = ""
|
|
} else {
|
|
val validator = BalanceValidator()
|
|
// TODO why attest=false?
|
|
validator.Check(ctx, false)
|
|
context?.let { ContextCompat.getColor(it, validator.color) }?.let { tvBalanceLine1.setTextColor(it) }
|
|
tvBalanceLine1.text = validator.firstLine
|
|
tvBalanceLine2.text = validator.getSecondLine(false)
|
|
}
|
|
|
|
val engine = CoinEngineFactory.create(ctx)
|
|
when {
|
|
engine!!.hasBalanceInfo() -> {
|
|
val html = Html.fromHtml(engine.balanceHTML)
|
|
tvBalance.text = html
|
|
tvBalanceEquivalent.text = engine.balanceEquivalent
|
|
}
|
|
ctx.card!!.offlineBalance != null -> {
|
|
val html = Html.fromHtml(engine.offlineBalanceHTML)
|
|
tvBalance.text = html
|
|
}
|
|
else -> tvBalance.text = getString(R.string.no_data_string)
|
|
}
|
|
|
|
tvWallet.text = ctx.coinData!!.wallet
|
|
|
|
if (ctx.card!!.tokenSymbol.length > 1) {
|
|
val html = Html.fromHtml(ctx.blockchainName)
|
|
tvBlockchain.text = html
|
|
} else
|
|
tvBlockchain.text = ctx.blockchainName
|
|
|
|
if (requestCounter==0 && engine.hasBalanceInfo()) {
|
|
btnExtract.isEnabled = true
|
|
btnExtract.backgroundTintList = activeColor
|
|
} else {
|
|
btnExtract.isEnabled = false
|
|
btnExtract.backgroundTintList = inactiveColor
|
|
}
|
|
|
|
//TODO why ???
|
|
// ctx.error = null
|
|
// ctx.message = null
|
|
}
|
|
|
|
private fun refresh() {
|
|
if (ctx.card == null) return
|
|
|
|
// clear all card data and request again
|
|
ctx.coinData.clearInfo()
|
|
ctx.error = null
|
|
ctx.message = null
|
|
|
|
Log.e(TAG, "============= START REFRESH")
|
|
requestCounter = 0
|
|
srl?.isRefreshing = true
|
|
|
|
updateViews()
|
|
|
|
requestVerifyAndGetInfo()
|
|
|
|
val coinEngine = CoinEngineFactory.create(ctx)
|
|
requestCounter++
|
|
coinEngine!!.requestBalanceAndUnspentTransactions(
|
|
object : CoinEngine.BlockchainRequestsCallbacks {
|
|
override fun onComplete(success: Boolean) {
|
|
Log.i(TAG, "requestBalanceAndUnspentTransactions onComplete: "+success.toString()+", request counter "+requestCounter.toString())
|
|
if( activity==null || !UtilHelper.isOnline(activity!!)) return
|
|
requestCounter--
|
|
if(! success)
|
|
{
|
|
Log.e(TAG, "ctx.error: "+ctx.error)
|
|
}
|
|
updateViews()
|
|
}
|
|
|
|
override fun onProgress() {
|
|
if( activity==null || !UtilHelper.isOnline(activity!!)) return
|
|
Log.i(TAG, "requestBalanceAndUnspentTransactions onProgress")
|
|
updateViews()
|
|
}
|
|
|
|
override fun allowAdvance(): Boolean {
|
|
return UtilHelper.isOnline(context as Activity)
|
|
}
|
|
}
|
|
)
|
|
|
|
|
|
// TODO - move requestRateInfo to CoinEngine
|
|
|
|
// Bitcoin
|
|
if (ctx.blockchain == Blockchain.Bitcoin || ctx.blockchain == Blockchain.BitcoinTestNet) {
|
|
ctx.coinData.setIsBalanceEqual(true)
|
|
|
|
requestRateInfo("bitcoin")
|
|
}
|
|
|
|
// Litecoin
|
|
if (ctx.blockchain == Blockchain.Litecoin) {
|
|
ctx.coinData.setIsBalanceEqual(true)
|
|
|
|
requestRateInfo("litecoin")
|
|
}
|
|
|
|
// BitcoinCash
|
|
else if (ctx.blockchain == Blockchain.BitcoinCash) {
|
|
ctx.coinData.setIsBalanceEqual(true)
|
|
requestRateInfo("bitcoin-cash")
|
|
}
|
|
|
|
// Ethereum
|
|
else if (ctx.blockchain == Blockchain.Ethereum || ctx.blockchain == Blockchain.EthereumTestNet) {
|
|
requestRateInfo("ethereum")
|
|
}
|
|
|
|
// Token
|
|
else if (ctx.blockchain == Blockchain.Token) {
|
|
requestRateInfo("ethereum")
|
|
}
|
|
}
|
|
|
|
private fun requestVerifyAndGetInfo() {
|
|
if (UtilHelper.isOnline(context as Activity)) {
|
|
if ((ctx.card!!.isOnlineVerified == null || !ctx.card!!.isOnlineVerified)) {
|
|
Log.i(TAG, "requestVerifyAndGetInfo")
|
|
requestCounter++
|
|
serverApiTangem.cardVerifyAndGetInfo(ctx.card)
|
|
}
|
|
} else {
|
|
Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
|
|
Log.e(TAG, "+++++++++++ Hide refresh 1")
|
|
srl?.isRefreshing = false
|
|
}
|
|
}
|
|
|
|
private fun requestRateInfo(cryptoId: String) {
|
|
if (UtilHelper.isOnline(context as Activity)) {
|
|
Log.i(TAG, "requestRateInfo")
|
|
serverApiCommon.rateInfoData(cryptoId)
|
|
} else {
|
|
Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
|
|
Log.e(TAG, "+++++++++++ Hide refresh 2")
|
|
srl?.isRefreshing = false
|
|
}
|
|
}
|
|
|
|
private fun startVerify(tag: Tag?) {
|
|
try {
|
|
val isoDep = IsoDep.get(tag)
|
|
?: throw CardProtocol.TangemException(getString(R.string.wrong_tag_err))
|
|
val uid = tag!!.id
|
|
val sUID = Util.byteArrayToHexString(uid)
|
|
if (ctx.card.uid != sUID) {
|
|
// Log.d(TAG, "Invalid UID: $sUID")
|
|
nfcManager.ignoreTag(isoDep.tag)
|
|
return
|
|
} else {
|
|
// Log.v(TAG, "UID: $sUID")
|
|
}
|
|
|
|
if (lastReadSuccess)
|
|
isoDep.timeout = 1000
|
|
else
|
|
isoDep.timeout = 65000
|
|
|
|
verifyCardTask = VerifyCardTask(ctx.card, NfcReader(nfcManager, isoDep), App.localStorage, App.pinStorage, App.firmwaresStorage, this)
|
|
verifyCardTask?.start()
|
|
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
}
|
|
}
|
|
|
|
private fun doShareWallet(useURI: Boolean) {
|
|
if (useURI) {
|
|
val engine = CoinEngineFactory.create(ctx)
|
|
val txtShare = engine!!.shareWalletUri.toString()
|
|
val intent = Intent(Intent.ACTION_SEND)
|
|
intent.type = "text/plain"
|
|
intent.putExtra(Intent.EXTRA_SUBJECT, "Wallet address")
|
|
intent.putExtra(Intent.EXTRA_TEXT, txtShare)
|
|
|
|
val packageManager = activity?.packageManager
|
|
val activities = packageManager?.queryIntentActivities(intent, PackageManager.MATCH_ALL)
|
|
val isIntentSafe = activities?.size!! > 0
|
|
|
|
if (isIntentSafe) {
|
|
// create intent to show chooser
|
|
val chooser = Intent.createChooser(intent, getString(R.string.share_wallet_address_with))
|
|
|
|
// verify the intent will resolve to at least one activity
|
|
if (intent.resolveActivity(activity!!.packageManager) != null) {
|
|
startActivity(chooser)
|
|
}
|
|
} else {
|
|
val clipboard = activity?.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
|
clipboard.primaryClip = ClipData.newPlainText(txtShare, txtShare)
|
|
Toast.makeText(activity, R.string.copied_clipboard, Toast.LENGTH_LONG).show()
|
|
}
|
|
} else {
|
|
val txtShare = ctx.coinData.wallet
|
|
val clipboard = activity?.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
|
clipboard.primaryClip = ClipData.newPlainText(txtShare, txtShare)
|
|
Toast.makeText(activity, R.string.copied_clipboard, Toast.LENGTH_LONG).show()
|
|
}
|
|
}
|
|
|
|
private var showTime: Date = Date()
|
|
|
|
private fun showSingleToast(text: Int) {
|
|
if (singleToast == null || !singleToast!!.view.isShown || showTime.time + 2000 < Date().time) {
|
|
if (singleToast != null)
|
|
singleToast!!.cancel()
|
|
singleToast = Toast.makeText(activity, text, Toast.LENGTH_LONG)
|
|
singleToast!!.show()
|
|
showTime = Date()
|
|
}
|
|
}
|
|
|
|
private fun showSingleToast(text: String) {
|
|
if (singleToast == null || !singleToast!!.view.isShown || showTime.time + 2000 < Date().time) {
|
|
if (singleToast != null)
|
|
singleToast!!.cancel()
|
|
singleToast = Toast.makeText(activity, text, Toast.LENGTH_LONG)
|
|
singleToast!!.show()
|
|
showTime = Date()
|
|
}
|
|
}
|
|
|
|
} |