diff --git a/.idea/navEditor.xml b/.idea/navEditor.xml
new file mode 100644
index 0000000000..5227e32389
--- /dev/null
+++ b/.idea/navEditor.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 84bce96abd..156881a178 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -30,7 +30,6 @@ android {
debuggable true
minifyEnabled false
applicationIdSuffix ".debug"
- versionNameSuffix '-DEBUG'
signingConfig signingConfigs.debug
}
}
@@ -67,12 +66,15 @@ dependencies {
// implementation 'com.github.TangemCash:card-common:0.1.2'
// implementation 'com.github.TangemCash:card-android:0.1.3'
// implementation 'com.github.TangemCash:server-android:0.1.4'
- implementation 'androidx.appcompat:appcompat:1.1.0-alpha04'
- implementation "androidx.preference:preference:1.1.0-alpha04"
- implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation 'android.arch.navigation:navigation-fragment:1.0.0'
+ implementation 'android.arch.navigation:navigation-ui-ktx:1.0.0'
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
+ implementation 'androidx.appcompat:appcompat:1.1.0-alpha04'
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation "androidx.preference:preference:1.1.0-alpha04"
implementation 'androidx.biometric:biometric:1.0.0-alpha04'
- implementation 'co.nstant.in:cbor:0.8'
implementation 'com.google.android.material:material:1.1.0-alpha05'
implementation 'com.google.dagger:dagger:2.21'
kapt 'com.google.dagger:dagger-compiler:2.21'
@@ -90,6 +92,7 @@ dependencies {
implementation 'com.skyfishjy.ripplebackground:library:1.0.1'
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
implementation "com.orhanobut:hawk:2.0.1"
+ implementation 'co.nstant.in:cbor:0.8'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0"
diff --git a/app/src/debug/res/values/strings.xml b/app/src/debug/res/values/strings.xml
index ec5cc446df..9ef8838437 100644
--- a/app/src/debug/res/values/strings.xml
+++ b/app/src/debug/res/values/strings.xml
@@ -1,6 +1,6 @@
-
+ DEBUG
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 07226da19f..c62a9f553b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -29,12 +29,13 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
-
-
-
-
-
-
+
+
(NfcAdapter.EXTRA_TAG)
if (tag != null) {
- val fragment = supportFragmentManager.findFragmentById(R.id.loaded_wallet_fragment) as LoadedWallet
+ val fragment = supportFragmentManager.findFragmentById(R.id.loaded_wallet_fragment) as LoadedWalletFragment
fragment.onTagDiscovered(tag)
}
}
diff --git a/app/src/main/java/com/tangem/ui/activity/MainActivity.kt b/app/src/main/java/com/tangem/ui/activity/MainActivity.kt
index 184cc0d391..075ff25409 100644
--- a/app/src/main/java/com/tangem/ui/activity/MainActivity.kt
+++ b/app/src/main/java/com/tangem/ui/activity/MainActivity.kt
@@ -3,151 +3,79 @@
package com.tangem.ui.activity
import android.Manifest
-import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.nfc.NfcAdapter
import android.nfc.Tag
-import android.nfc.tech.IsoDep
import android.os.Bundle
-import android.view.Menu
-import android.view.MenuItem
-import android.view.View
-import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
-import androidx.appcompat.widget.PopupMenu
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
+import androidx.navigation.NavController
+import androidx.navigation.Navigation
import com.scottyab.rootbeer.RootBeer
import com.tangem.App
import com.tangem.Constant
-import com.tangem.card_android.android.nfc.NfcDeviceAntennaLocation
-import com.tangem.card_android.android.nfc.NfcLifecycleObserver
import com.tangem.card_android.android.reader.NfcManager
-import com.tangem.card_android.android.reader.NfcReader
-import com.tangem.card_android.data.EXTRA_TANGEM_CARD
-import com.tangem.card_android.data.EXTRA_TANGEM_CARD_UID
-import com.tangem.card_android.data.loadFromBundle
-import com.tangem.card_android.data.saveToBundle
-import com.tangem.card_common.data.TangemCard
-import com.tangem.card_common.reader.CardProtocol
-import com.tangem.card_common.tasks.CustomReadCardTask
-import com.tangem.card_common.tasks.ReadCardInfoTask
-import com.tangem.data.Logger
-import com.tangem.data.network.ServerApiCommon
import com.tangem.di.Navigator
import com.tangem.di.ToastHelper
-import com.tangem.wallet.CoinEngineFactory
-import com.tangem.wallet.TangemContext
-import com.tangem.ui.dialog.NoExtendedLengthSupportDialog
import com.tangem.ui.dialog.RootFoundDialog
-import com.tangem.ui.dialog.WaitSecurityDelayDialog
-import com.tangem.util.CommonUtil
-import com.tangem.util.LOG
-import com.tangem.util.UtilHelper
import com.tangem.wallet.BuildConfig
import com.tangem.wallet.R
-import kotlinx.android.synthetic.main.activity_main.*
-import kotlinx.android.synthetic.main.layout_touch_card.*
-import java.io.File
-import java.util.*
import javax.inject.Inject
-class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtocol.Notifications, PopupMenu.OnMenuItemClickListener {
+class MainActivity : AppCompatActivity() {
companion object {
val TAG: String = MainActivity::class.java.simpleName
fun callingIntent(context: Context) = Intent(context, MainActivity::class.java)
}
+ lateinit var navController: NavController
@Inject
internal lateinit var navigator: Navigator
@Inject
internal lateinit var toastHelper: ToastHelper
- private lateinit var nfcManager: NfcManager
+// private var onNfcReaderCallback: NfcAdapter.ReaderCallback? = null
- private var zipFile: File? = null
- private lateinit var nfcDeviceAntenna: NfcDeviceAntennaLocation
- private var unsuccessReadCount = 0
- private var lastTag: Tag? = null
- private var task: CustomReadCardTask? = null
- private var onNfcReaderCallback: NfcAdapter.ReaderCallback? = null
-
- override fun onNewIntent(intent: Intent?) {
- super.onNewIntent(intent)
- if (intent != null && (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action || NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action)) {
- val tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
- if (tag != null && onNfcReaderCallback != null)
- onNfcReaderCallback!!.onTagDiscovered(tag)
- }
- }
+// override fun onNewIntent(intent: Intent?) {
+// super.onNewIntent(intent)
+// if (intent != null && (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action || NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action)) {
+// val tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
+// if (tag != null && onNfcReaderCallback != null)
+// onNfcReaderCallback?.onTagDiscovered(tag)
+// }
+// }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
+ navController = Navigation.findNavController(this, R.id.nav_host_fragment)
+
App.navigatorComponent.inject(this)
App.toastHelperComponent.inject(this)
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
- nfcManager = NfcManager(this, this)
- lifecycle.addObserver(NfcLifecycleObserver(nfcManager))
-
verifyPermissions()
- requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
-
- setNfcAdapterReaderCallback(this)
-
- rippleBackgroundNfc.startRippleAnimation()
-
- // init NFC Antenna
- nfcDeviceAntenna = NfcDeviceAntennaLocation(this, ivHandCardHorizontal, ivHandCardVertical, llHand, llNfc)
- nfcDeviceAntenna.init()
-
- // set phone name
- if (nfcDeviceAntenna.fullName != "")
- tvNFCHint.text = String.format(getString(R.string.scan_banknote), nfcDeviceAntenna.fullName)
- else
- tvNFCHint.text = String.format(getString(R.string.scan_banknote), getString(R.string.phone))
-
- // NFC
- val intent = intent
- if (intent != null && (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action || NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action)) {
- val tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
- if (tag != null && onNfcReaderCallback != null) {
- onNfcReaderCallback?.onTagDiscovered(tag)
- }
- }
+// // NFC
+// val intent = intent
+// if (intent != null && (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action || NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action)) {
+// val tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
+// if (tag != null && onNfcReaderCallback != null) {
+// onNfcReaderCallback?.onTagDiscovered(tag)
+// }
+// }
// check if root device
val rootBeer = RootBeer(this)
if (rootBeer.isRootedWithoutBusyBoxCheck && !BuildConfig.DEBUG)
RootFoundDialog().show(supportFragmentManager, RootFoundDialog.TAG)
-
- // set listeners
- fab.setOnClickListener { showMenu(it) }
-
- val apiHelper = ServerApiCommon()
- apiHelper.setLastVersionListener { response ->
- try {
- if (response.isNullOrEmpty())
- return@setLastVersionListener
- val responseVersionName = response.trim(' ', '\n', '\r', '\t')
- val responseBuildVersion = responseVersionName.split('.').last()
- val appBuildVersion = BuildConfig.VERSION_NAME.split('.').last()
- if (responseBuildVersion.toInt() > appBuildVersion.toInt())
- if (BuildConfig.FLAVOR.equals(Constant.FLAVOR_TANGEM_ACCESS))
- toastHelper.showSnackbarUpdateVersion(this, cl, responseVersionName)
- } catch (E: Exception) {
- E.printStackTrace()
- }
- }
- apiHelper.requestLastVersion()
}
private fun verifyPermissions() {
@@ -157,231 +85,4 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
}
}
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- when (requestCode) {
- Constant.REQUEST_CODE_SEND_EMAIL -> {
- if (zipFile != null) {
- zipFile!!.delete()
- zipFile = null
- }
- }
- Constant.REQUEST_CODE_ENTER_PIN_ACTIVITY -> {
- if (resultCode == Activity.RESULT_OK && lastTag != null)
- onTagDiscovered(lastTag!!)
- else
- ReadCardInfoTask.resetLastReadInfo()
- }
- }
- super.onActivityResult(requestCode, resultCode, data)
- }
-
- override fun onMenuItemClick(item: MenuItem): Boolean {
- return onOptionsItemSelected(item)
- }
-
- override fun onCreateOptionsMenu(menu: Menu): Boolean {
- menuInflater.inflate(R.menu.menu_main, menu)
- if (BuildConfig.DEBUG) {
- for (i in 0 until menu.size()) menu.getItem(i).isVisible = true
- }
- return true
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- val id = item.itemId
- when (id) {
- R.id.sendLogs -> {
- var f: File? = null
- try {
- f = Logger.collectLogs(this)
- if (f != null) {
- LOG.e(TAG, String.format("Collect %d log bytes", f.length()))
- CommonUtil.sendEmail(this, zipFile, TAG, "Logs", UtilHelper.getDeviceInfo(), arrayOf(f))
- } else {
- LOG.e(TAG, "Can't create temporarily log file")
- }
- } catch (e: Exception) {
- e.printStackTrace()
- } finally {
- if (f != null && f.exists())
- f.delete()
- }
- return true
- }
- R.id.managePIN -> {
- navigator.showPinSave(this, false)
- return true
- }
-
- R.id.managePIN2 -> {
- navigator.showPinSave(this, true)
- return true
- }
-
- R.id.settings -> {
- navigator.showSettings(this)
- return true
- }
-
- R.id.about -> {
- navigator.showLogo(this, false)
- return true
- }
- }
- return super.onOptionsItemSelected(item)
- }
-
- override fun onTagDiscovered(tag: Tag) {
- try {
- // get IsoDep handle and run cardReader thread
- val isoDep = IsoDep.get(tag)
- if (unsuccessReadCount < 2)
- isoDep.timeout = 2000 + 5000 * unsuccessReadCount
- else
- isoDep.timeout = 90000
-
- lastTag = tag
-
- task = ReadCardInfoTask(NfcReader(nfcManager, isoDep), App.localStorage, App.pinStorage, this)
- task?.start()
- } catch (e: Exception) {
- e.printStackTrace()
- nfcManager.notifyReadResult(false)
- }
- }
-
- public override fun onResume() {
- super.onResume()
- nfcDeviceAntenna.animate()
- ReadCardInfoTask.resetLastReadInfo()
- }
-
- public override fun onPause() {
- task?.cancel(true)
- super.onPause()
- }
-
- public override fun onStop() {
- task?.cancel(true)
- super.onStop()
- }
-
- override fun onReadStart(cardProtocol: CardProtocol) {
- rlProgressBar.post { rlProgressBar.visibility = View.VISIBLE }
- }
-
- override fun onReadProgress(protocol: CardProtocol, progress: Int) {
-
- }
-
- override fun onReadFinish(cardProtocol: CardProtocol?) {
- task = null
- if (cardProtocol != null) {
- if (cardProtocol.error == null) {
- nfcManager.notifyReadResult(true)
- rlProgressBar.post {
- rlProgressBar.visibility = View.GONE
-
- // TODO - ??? remove save and load???
- val cardInfo = Bundle()
- val bCard = Bundle()
-
- cardInfo.putString(EXTRA_TANGEM_CARD_UID, cardProtocol.card.uid)
- cardInfo.putBundle(EXTRA_TANGEM_CARD, bCard)
- cardProtocol.card.saveToBundle(bCard)
-
- val uid = cardInfo.getString(EXTRA_TANGEM_CARD_UID)
- val card = TangemCard(uid)
- cardInfo.getBundle(EXTRA_TANGEM_CARD)?.let { card.loadFromBundle(it) }
-
- val ctx = TangemContext(card)
- when {
- card.status == TangemCard.Status.Loaded -> lastTag?.let {
- val engineCoin = CoinEngineFactory.create(ctx)
- if (engineCoin != null) {
- engineCoin.defineWallet()
- navigator.showLoadedWallet(this, it, ctx)
- }
- }
- card.status == TangemCard.Status.Empty -> navigator.showEmptyWallet(this, ctx)
- card.status == TangemCard.Status.Purged -> Toast.makeText(this, R.string.erased_wallet, Toast.LENGTH_SHORT).show()
- card.status == TangemCard.Status.NotPersonalized -> Toast.makeText(this, R.string.not_personalized, Toast.LENGTH_SHORT).show()
- else -> lastTag?.let { navigator.showLoadedWallet(this, it, ctx) }
- }
- }
-
- } else {
- // remove last UIDs because of error and no card read
- rlProgressBar.post {
- Toast.makeText(this, R.string.try_to_scan_again, Toast.LENGTH_SHORT).show()
- unsuccessReadCount++
-
- if (cardProtocol.error is CardProtocol.TangemException_InvalidPIN)
- navigator.showPinRequest(this, PinRequestActivity.Mode.RequestPIN.toString())
- else {
- if (cardProtocol.error is CardProtocol.TangemException_ExtendedLengthNotSupported)
- if (!NoExtendedLengthSupportDialog.allReadyShowed)
- NoExtendedLengthSupportDialog().show(supportFragmentManager, NoExtendedLengthSupportDialog.TAG)
-
- lastTag = null
- ReadCardInfoTask.resetLastReadInfo()
- nfcManager.notifyReadResult(false)
- }
- }
- }
- }
-
- rlProgressBar.postDelayed({
- try {
- rlProgressBar.visibility = View.GONE
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }, 500)
- }
-
- override fun onReadCancel() {
- task = null
- ReadCardInfoTask.resetLastReadInfo()
- rlProgressBar.postDelayed({
- try {
- rlProgressBar.visibility = View.GONE
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }, 500)
- }
-
- override fun onReadWait(msec: Int) {
- WaitSecurityDelayDialog.onReadWait(Objects.requireNonNull(this), msec)
- }
-
- override fun onReadBeforeRequest(timeout: Int) {
- WaitSecurityDelayDialog.onReadBeforeRequest(Objects.requireNonNull(this), timeout)
- }
-
- override fun onReadAfterRequest() {
- WaitSecurityDelayDialog.onReadAfterRequest(Objects.requireNonNull(this))
- }
-
- private fun setNfcAdapterReaderCallback(callback: NfcAdapter.ReaderCallback) {
- onNfcReaderCallback = callback
- }
-
- private fun showMenu(v: View) {
- val popup = PopupMenu(this, v)
- val inflater = popup.menuInflater
- inflater.inflate(R.menu.menu_main, popup.menu)
-
- if (BuildConfig.DEBUG) {
- popup.menu.findItem(R.id.managePIN).isEnabled = true
- popup.menu.findItem(R.id.managePIN2).isEnabled = true
- popup.menu.findItem(R.id.sendLogs).isVisible = true
- popup.menu.findItem(R.id.settings).isVisible = true
- }
-
- popup.setOnMenuItemClickListener(this)
- popup.show()
- }
-
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/ui/activity/PinRequestActivity.kt b/app/src/main/java/com/tangem/ui/activity/PinRequestActivity.kt
index c5570a6285..a881cc687d 100644
--- a/app/src/main/java/com/tangem/ui/activity/PinRequestActivity.kt
+++ b/app/src/main/java/com/tangem/ui/activity/PinRequestActivity.kt
@@ -246,7 +246,7 @@ class PinRequestActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, Finge
@SuppressLint("NewApi")
private fun testFingerPrintSettings(): Boolean {
- LOG.i(TAG, "Testing Fingerprint Settings")
+ LOG.i(TAG, "Testing Fingerprint SettingsFragment")
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
fingerprintManager = getSystemService(Context.FINGERPRINT_SERVICE) as FingerprintManager
diff --git a/app/src/main/java/com/tangem/ui/fragment/LoadedWallet.kt b/app/src/main/java/com/tangem/ui/fragment/LoadedWalletFragment.kt
similarity index 94%
rename from app/src/main/java/com/tangem/ui/fragment/LoadedWallet.kt
rename to app/src/main/java/com/tangem/ui/fragment/LoadedWalletFragment.kt
index 4dd0dccb7f..b908c578a2 100644
--- a/app/src/main/java/com/tangem/ui/fragment/LoadedWallet.kt
+++ b/app/src/main/java/com/tangem/ui/fragment/LoadedWalletFragment.kt
@@ -13,6 +13,7 @@ import android.nfc.tech.IsoDep
import android.os.Build
import android.os.Bundle
import android.text.Html
+import android.util.Log
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
@@ -20,6 +21,8 @@ import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
import com.tangem.App
import com.tangem.Constant
import com.tangem.data.Blockchain
@@ -63,11 +66,12 @@ import java.io.InputStream
import java.util.*
import kotlin.concurrent.timerTask
-class LoadedWallet : androidx.fragment.app.Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notifications, SharedPreferences.OnSharedPreferenceChangeListener {
+class LoadedWalletFragment : androidx.fragment.app.Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notifications, SharedPreferences.OnSharedPreferenceChangeListener {
companion object {
- val TAG: String = LoadedWallet::class.java.simpleName
+ val TAG: String = LoadedWalletFragment::class.java.simpleName
}
+ private lateinit var viewModel: LoadedWalletViewModel
private lateinit var ctx: TangemContext
private lateinit var nfcManager: NfcManager
private lateinit var mpSecondScanSound: MediaPlayer
@@ -274,19 +278,23 @@ class LoadedWallet : androidx.fragment.app.Fragment(), NfcAdapter.ReaderCallback
}
serverApiTangem.setArtworkListener(artworkListener)
- // request rate info listener
- serverApiCommon.setRateInfoListener {
- if (activity == null || !UtilHelper.isOnline(activity!!)) return@setRateInfoListener
- val rate = it.priceUsd.toFloat()
- ctx.coinData!!.rate = rate
- ctx.coinData!!.rateAlter = rate
- }
-
refresh()
startVerify(lastTag)
}
+ override fun onActivityCreated(savedInstanceState: Bundle?) {
+ super.onActivityCreated(savedInstanceState)
+ viewModel = ViewModelProviders.of(this).get(LoadedWalletViewModel::class.java)
+
+ // set rate info to CoinData
+ viewModel.getRateInfo().observe(this, Observer { rate ->
+ ctx.coinData.rate = rate
+ ctx.coinData.rateAlter = rate
+ })
+ viewModel.requestRateInfo(ctx)
+ }
+
override fun onPause() {
super.onPause()
if (timerHideErrorAndMessage != null) {
@@ -647,7 +655,8 @@ class LoadedWallet : androidx.fragment.app.Fragment(), NfcAdapter.ReaderCallback
requestBalanceAndUnspentTransactions()
- requestRateInfo()
+ if (::viewModel.isInitialized)
+ viewModel.requestRateInfo(ctx)
if (requestCounter == 0) {
// if no connection and no requests posted
@@ -709,37 +718,6 @@ class LoadedWallet : androidx.fragment.app.Fragment(), NfcAdapter.ReaderCallback
}
}
- private fun requestRateInfo() {
- if (UtilHelper.isOnline(context as Activity)) {
- LOG.i(TAG, "requestRateInfo")
-
- // TODO - move requestRateInfo to CoinEngine
- val cryptoId: String = when (ctx.blockchain) {
- Blockchain.Bitcoin -> "bitcoin"
- Blockchain.BitcoinTestNet -> "bitcoin"
- Blockchain.Ethereum -> "ethereum"
- Blockchain.EthereumTestNet -> "ethereum"
- Blockchain.Token -> "ethereum"
- Blockchain.NftToken -> "ethereum"
- Blockchain.BitcoinCash -> "bitcoin-cash"
- Blockchain.Litecoin -> "litecoin"
- Blockchain.Rootstock -> "bitcoin"
- Blockchain.RootstockToken -> "bitcoin"
- Blockchain.Cardano -> "cardano"
- Blockchain.Ripple -> "ripple"
- Blockchain.Binance -> "binance-coin"
- Blockchain.BinanceTestNet -> "binance-coin"
- else -> {
- throw Exception("Can''t get rate for blockchain " + ctx.blockchainName)
- }
- }
- serverApiCommon.requestRateInfo(cryptoId)
- } else {
- ctx.error = getString(R.string.no_connection)
- updateViews()
- }
- }
-
private fun startVerify(tag: Tag?) {
try {
val isoDep = IsoDep.get(tag)
diff --git a/app/src/main/java/com/tangem/ui/fragment/LoadedWalletViewModel.kt b/app/src/main/java/com/tangem/ui/fragment/LoadedWalletViewModel.kt
new file mode 100644
index 0000000000..0894729b9d
--- /dev/null
+++ b/app/src/main/java/com/tangem/ui/fragment/LoadedWalletViewModel.kt
@@ -0,0 +1,52 @@
+package com.tangem.ui.fragment
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.tangem.data.Blockchain
+import com.tangem.data.network.ServerApiCommon
+import com.tangem.wallet.TangemContext
+
+class LoadedWalletViewModel : ViewModel() {
+ private var serverApiCommon: ServerApiCommon = ServerApiCommon()
+ private lateinit var ctx: TangemContext
+ private val rate: MutableLiveData by lazy {
+ MutableLiveData().also {
+ loadRateInfo()
+ }
+ }
+
+ fun getRateInfo(): LiveData {
+ return rate
+ }
+
+ fun requestRateInfo(ctx: TangemContext) {
+ this.ctx = ctx
+ // TODO - move loadRateInfo to CoinEngine
+ val cryptoId: String = when (ctx.blockchain) {
+ Blockchain.Bitcoin -> "bitcoin"
+ Blockchain.BitcoinTestNet -> "bitcoin"
+ Blockchain.Ethereum -> "ethereum"
+ Blockchain.EthereumTestNet -> "ethereum"
+ Blockchain.Token -> "ethereum"
+ Blockchain.NftToken -> "ethereum"
+ Blockchain.BitcoinCash -> "bitcoin-cash"
+ Blockchain.Litecoin -> "litecoin"
+ Blockchain.Rootstock -> "bitcoin"
+ Blockchain.RootstockToken -> "bitcoin"
+ Blockchain.Cardano -> "cardano"
+ Blockchain.Ripple -> "ripple"
+ else -> {
+ throw Exception("Can''t get rate for blockchain " + ctx.blockchainName)
+ }
+ }
+ serverApiCommon.requestRateInfo(cryptoId)
+ }
+
+ private fun loadRateInfo() {
+ serverApiCommon.setRateInfoListener {
+ val rate = it.priceUsd.toFloat()
+ this.rate.value = rate
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/ui/fragment/MainFragment.kt b/app/src/main/java/com/tangem/ui/fragment/MainFragment.kt
new file mode 100644
index 0000000000..7f331b7aad
--- /dev/null
+++ b/app/src/main/java/com/tangem/ui/fragment/MainFragment.kt
@@ -0,0 +1,340 @@
+package com.tangem.ui.fragment
+
+import android.app.Activity
+import android.content.Intent
+import android.nfc.NfcAdapter
+import android.nfc.Tag
+import android.nfc.tech.IsoDep
+import android.os.Bundle
+import android.view.*
+import android.widget.PopupMenu
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
+import com.tangem.App
+import com.tangem.Constant
+import com.tangem.card_android.android.nfc.NfcDeviceAntennaLocation
+import com.tangem.card_android.android.nfc.NfcLifecycleObserver
+import com.tangem.card_android.android.reader.NfcManager
+import com.tangem.card_android.android.reader.NfcReader
+import com.tangem.card_android.data.EXTRA_TANGEM_CARD
+import com.tangem.card_android.data.EXTRA_TANGEM_CARD_UID
+import com.tangem.card_android.data.loadFromBundle
+import com.tangem.card_android.data.saveToBundle
+import com.tangem.card_common.data.TangemCard
+import com.tangem.card_common.reader.CardProtocol
+import com.tangem.card_common.tasks.CustomReadCardTask
+import com.tangem.card_common.tasks.ReadCardInfoTask
+import com.tangem.data.Logger
+import com.tangem.data.network.ServerApiCommon
+import com.tangem.ui.activity.MainActivity
+import com.tangem.ui.activity.PinRequestActivity
+import com.tangem.ui.dialog.NoExtendedLengthSupportDialog
+import com.tangem.ui.dialog.WaitSecurityDelayDialog
+import com.tangem.util.CommonUtil
+import com.tangem.util.LOG
+import com.tangem.util.UtilHelper
+import com.tangem.wallet.BuildConfig
+import com.tangem.wallet.CoinEngineFactory
+import com.tangem.wallet.R
+import com.tangem.wallet.TangemContext
+import kotlinx.android.synthetic.main.layout_touch_card.*
+import kotlinx.android.synthetic.main.main_fragment.*
+import java.io.File
+import java.util.*
+
+class MainFragment : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notifications, androidx.appcompat.widget.PopupMenu.OnMenuItemClickListener, PopupMenu.OnMenuItemClickListener {
+
+ companion object {
+ fun newInstance() = MainFragment()
+ val TAG: String = MainFragment::class.java.simpleName
+ }
+
+ private lateinit var viewModel: MainViewModel
+ private lateinit var nfcDeviceAntenna: NfcDeviceAntennaLocation
+ private var unsuccessReadCount = 0
+ private lateinit var nfcManager: NfcManager
+ private var task: CustomReadCardTask? = null
+ private var lastTag: Tag? = null
+ private var zipFile: File? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ nfcManager = NfcManager(activity!!, this)
+ lifecycle.addObserver(NfcLifecycleObserver(nfcManager))
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ setHasOptionsMenu(true)
+ return inflater.inflate(R.layout.main_fragment, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ rippleBackgroundNfc.startRippleAnimation()
+
+ // init NFC Antenna
+ nfcDeviceAntenna = NfcDeviceAntennaLocation(context!!, ivHandCardHorizontal, ivHandCardVertical, llHand, llNfc)
+ nfcDeviceAntenna.init()
+
+ // set phone name
+ if (nfcDeviceAntenna.fullName != "")
+ tvNFCHint.text = String.format(getString(R.string.scan_banknote), nfcDeviceAntenna.fullName)
+ else
+ tvNFCHint.text = String.format(getString(R.string.scan_banknote), getString(R.string.phone))
+
+ // set listeners
+ fab.setOnClickListener { showMenu(it) }
+ }
+
+ override fun onActivityCreated(savedInstanceState: Bundle?) {
+ super.onActivityCreated(savedInstanceState)
+ viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
+
+ // show snackbar about new version app
+ viewModel.getVersionName().observe(this, Observer { text ->
+ (activity as MainActivity).toastHelper.showSnackbarUpdateVersion(context!!, cl, text)
+ })
+ }
+
+ override fun onResume() {
+ super.onResume()
+ nfcDeviceAntenna.animate()
+ }
+
+ override fun onPause() {
+ task?.cancel(true)
+ super.onPause()
+ }
+
+ override fun onStop() {
+ task?.cancel(true)
+ super.onStop()
+ }
+
+ override fun onTagDiscovered(tag: Tag) {
+ try {
+ // get IsoDep handle and run cardReader thread
+ val isoDep = IsoDep.get(tag)
+ if (unsuccessReadCount < 2)
+ isoDep.timeout = 2000 + 5000 * unsuccessReadCount
+ else
+ isoDep.timeout = 90000
+
+ lastTag = tag
+
+ task = ReadCardInfoTask(NfcReader(nfcManager, isoDep), App.localStorage, App.pinStorage, this)
+ task?.start()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ nfcManager.notifyReadResult(false)
+ }
+ }
+
+ override fun onReadStart(cardProtocol: CardProtocol) {
+ rlProgressBar?.post { rlProgressBar?.visibility = View.VISIBLE }
+ }
+
+ override fun onReadProgress(protocol: CardProtocol, progress: Int) {
+
+ }
+
+ override fun onReadFinish(cardProtocol: CardProtocol?) {
+ task = null
+ if (cardProtocol != null) {
+ if (cardProtocol.error == null) {
+ nfcManager.notifyReadResult(true)
+ rlProgressBar?.post {
+ rlProgressBar?.visibility = View.GONE
+
+ // TODO - ??? remove save and load???
+ val cardInfo = Bundle()
+ val bCard = Bundle()
+
+ cardInfo.putString(EXTRA_TANGEM_CARD_UID, cardProtocol.card.uid)
+ cardInfo.putBundle(EXTRA_TANGEM_CARD, bCard)
+ cardProtocol.card.saveToBundle(bCard)
+
+ val uid = cardInfo.getString(EXTRA_TANGEM_CARD_UID)
+ val card = TangemCard(uid)
+ cardInfo.getBundle(EXTRA_TANGEM_CARD)?.let { card.loadFromBundle(it) }
+
+ val ctx = TangemContext(card)
+ when {
+ card.status == TangemCard.Status.Loaded -> lastTag?.let {
+ val engineCoin = CoinEngineFactory.create(ctx)
+ if (engineCoin != null) {
+ engineCoin.defineWallet()
+
+// val bundle = Bundle()
+// bundle.putParcelable(Constant.EXTRA_LAST_DISCOVERED_TAG, lastTag)
+// ctx.saveToBundle(bundle)
+// (activity as MainActivity).navController.navigate(R.id.loadedWallet, bundle)
+
+ (activity as MainActivity).navigator.showLoadedWallet(activity!!, it, ctx)
+ }
+ }
+ card.status == TangemCard.Status.Empty -> (activity as MainActivity).navigator.showEmptyWallet(activity!!, ctx)
+ card.status == TangemCard.Status.Purged -> Toast.makeText(context, R.string.erased_wallet, Toast.LENGTH_SHORT).show()
+ card.status == TangemCard.Status.NotPersonalized -> Toast.makeText(context, R.string.not_personalized, Toast.LENGTH_SHORT).show()
+ else -> {
+
+// val bundle = Bundle()
+// bundle.putParcelable(Constant.EXTRA_LAST_DISCOVERED_TAG, lastTag)
+// ctx.saveToBundle(bundle)
+// navController.navigate(R.id.loadedWallet, bundle)
+
+// lastTag?.let { navigator.showLoadedWallet(this, it, ctx) }
+ }
+ }
+ }
+
+ } else {
+ // remove last UIDs because of error and no card read
+ rlProgressBar.post {
+ Toast.makeText(context, R.string.try_to_scan_again, Toast.LENGTH_SHORT).show()
+ unsuccessReadCount++
+
+ if (cardProtocol.error is CardProtocol.TangemException_InvalidPIN)
+ (activity as MainActivity).navigator.showPinRequest(activity!!, PinRequestActivity.Mode.RequestPIN.toString())
+ else {
+ if (cardProtocol.error is CardProtocol.TangemException_ExtendedLengthNotSupported)
+ if (!NoExtendedLengthSupportDialog.allReadyShowed)
+ NoExtendedLengthSupportDialog().show(activity!!.supportFragmentManager, NoExtendedLengthSupportDialog.TAG)
+
+ lastTag = null
+ ReadCardInfoTask.resetLastReadInfo()
+ nfcManager.notifyReadResult(false)
+ }
+ }
+ }
+ }
+
+ rlProgressBar.postDelayed({
+ try {
+ rlProgressBar.visibility = View.GONE
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }, 500)
+ }
+
+ override fun onReadCancel() {
+ task = null
+ ReadCardInfoTask.resetLastReadInfo()
+ rlProgressBar.postDelayed({
+ try {
+ rlProgressBar.visibility = View.GONE
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }, 500)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ when (requestCode) {
+ Constant.REQUEST_CODE_SEND_EMAIL -> {
+ if (zipFile != null) {
+ zipFile!!.delete()
+ zipFile = null
+ }
+ }
+ Constant.REQUEST_CODE_ENTER_PIN_ACTIVITY -> {
+ if (resultCode == Activity.RESULT_OK && lastTag != null)
+ onTagDiscovered(lastTag!!)
+ else
+ ReadCardInfoTask.resetLastReadInfo()
+ }
+ }
+ super.onActivityResult(requestCode, resultCode, data)
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+ inflater.inflate(R.menu.menu_main, menu)
+ if (BuildConfig.DEBUG) {
+ for (i in 0 until menu.size()) menu.getItem(i).isVisible = true
+ }
+ super.onCreateOptionsMenu(menu, inflater)
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ R.id.sendLogs -> {
+ var f: File? = null
+ try {
+ f = Logger.collectLogs(activity)
+ if (f != null) {
+ LOG.e(TAG, String.format("Collect %d log bytes", f.length()))
+ CommonUtil.sendEmail(activity, zipFile, TAG, "Logs", UtilHelper.getDeviceInfo(), arrayOf(f))
+ } else {
+ LOG.e(TAG, "Can't create temporarily log file")
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ } finally {
+ if (f != null && f.exists())
+ f.delete()
+ }
+ return true
+ }
+ R.id.managePIN -> {
+ (activity as MainActivity).navigator.showPinSave(activity!!, false)
+// (activity as MainActivity).navController.navigate(R.id.pinSaveActivity)
+ return true
+ }
+
+ R.id.managePIN2 -> {
+ (activity as MainActivity).navigator.showPinSave(activity!!, true)
+// (activity as MainActivity).navController.navigate(R.id.pinSaveActivity)
+ return true
+ }
+
+ R.id.settings -> {
+ (activity as MainActivity).navigator.showSettings(activity!!)
+// (activity as MainActivity).navController.navigate(R.id.settingsActivity)
+ return true
+ }
+
+ R.id.about -> {
+ (activity as MainActivity).navigator.showLogo(activity!!, false)
+// (activity as MainActivity).navController.navigate(R.id.logoActivity)
+ return true
+ }
+ }
+ return super.onOptionsItemSelected(item)
+ }
+
+ override fun onReadWait(msec: Int) {
+ WaitSecurityDelayDialog.onReadWait(Objects.requireNonNull(activity) as AppCompatActivity?, msec)
+ }
+
+ override fun onReadBeforeRequest(timeout: Int) {
+ WaitSecurityDelayDialog.onReadBeforeRequest(Objects.requireNonNull(activity) as AppCompatActivity?, timeout)
+ }
+
+ override fun onReadAfterRequest() {
+ WaitSecurityDelayDialog.onReadAfterRequest(Objects.requireNonNull(activity))
+ }
+
+ override fun onMenuItemClick(item: MenuItem?): Boolean {
+ return onOptionsItemSelected(item!!)
+ }
+
+ private fun showMenu(v: View) {
+ val popup = PopupMenu(context, v)
+ val inflater = popup.menuInflater
+ inflater.inflate(R.menu.menu_main, popup.menu)
+
+ if (BuildConfig.DEBUG) {
+ popup.menu.findItem(R.id.managePIN).isEnabled = true
+ popup.menu.findItem(R.id.managePIN2).isEnabled = true
+ popup.menu.findItem(R.id.sendLogs).isVisible = true
+ }
+
+ popup.setOnMenuItemClickListener(this)
+ popup.show()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/ui/fragment/MainViewModel.kt b/app/src/main/java/com/tangem/ui/fragment/MainViewModel.kt
new file mode 100644
index 0000000000..d9b47667c1
--- /dev/null
+++ b/app/src/main/java/com/tangem/ui/fragment/MainViewModel.kt
@@ -0,0 +1,38 @@
+package com.tangem.ui.fragment
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.tangem.Constant
+import com.tangem.data.network.ServerApiCommon
+import com.tangem.wallet.BuildConfig
+
+class MainViewModel : ViewModel() {
+ private var serverApiCommon: ServerApiCommon = ServerApiCommon()
+
+ private var versionName = MutableLiveData()
+
+ fun getVersionName(): LiveData {
+ versionName = MutableLiveData()
+ requestVersionName()
+ return versionName
+ }
+
+ private fun requestVersionName() {
+ serverApiCommon.setLastVersionListener { response ->
+ try {
+ if (response.isNullOrEmpty())
+ return@setLastVersionListener
+ val responseVersionName = response.trim(' ', '\n', '\r', '\t')
+ val responseBuildVersion = responseVersionName.split('.').last()
+ val appBuildVersion = BuildConfig.VERSION_NAME.split('.').last()
+ if (responseBuildVersion.toInt() > appBuildVersion.toInt())
+ if (BuildConfig.FLAVOR.equals(Constant.FLAVOR_TANGEM_ACCESS))
+ versionName.value = responseVersionName
+ } catch (E: Exception) {
+ E.printStackTrace()
+ }
+ }
+ serverApiCommon.requestLastVersion()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/ui/fragment/Settings.kt b/app/src/main/java/com/tangem/ui/fragment/Settings.kt
deleted file mode 100644
index a2a54a60e4..0000000000
--- a/app/src/main/java/com/tangem/ui/fragment/Settings.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.tangem.ui.fragment
-
-import android.os.Bundle
-import androidx.preference.PreferenceFragmentCompat
-import com.tangem.wallet.R
-
-class Settings : PreferenceFragmentCompat() {
- override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
- addPreferencesFromResource(R.xml.pref_main)
- }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/ui/fragment/SettingsFragment.kt b/app/src/main/java/com/tangem/ui/fragment/SettingsFragment.kt
new file mode 100644
index 0000000000..95f604cba2
--- /dev/null
+++ b/app/src/main/java/com/tangem/ui/fragment/SettingsFragment.kt
@@ -0,0 +1,25 @@
+package com.tangem.ui.fragment
+
+import android.os.Bundle
+import androidx.preference.ListPreference
+import androidx.preference.Preference
+import androidx.preference.PreferenceCategory
+import androidx.preference.PreferenceFragmentCompat
+import com.tangem.wallet.BuildConfig
+import com.tangem.wallet.R
+
+class SettingsFragment : PreferenceFragmentCompat() {
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ addPreferencesFromResource(R.xml.pref_main)
+
+ val categoryCommon = findPreference(getString(R.string.pref_category_common))
+ val selectNodes = findPreference(getString(R.string.pref_select_nodes))
+ val encryptionModes = findPreference(getString(R.string.pref_encryption_modes))
+
+ if (!BuildConfig.DEBUG) {
+ categoryCommon?.removePreference(selectNodes)
+ categoryCommon?.removePreference(encryptionModes)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/wallet/TangemContext.java b/app/src/main/java/com/tangem/wallet/TangemContext.java
index 3a0ee4e444..9c2d9bbfa2 100644
--- a/app/src/main/java/com/tangem/wallet/TangemContext.java
+++ b/app/src/main/java/com/tangem/wallet/TangemContext.java
@@ -22,6 +22,7 @@ public class TangemContext {
}
public TangemContext(TangemCard card) {
+
this.card = card;
}
@@ -135,6 +136,21 @@ public class TangemContext {
return tangemContext;
}
+ public void saveToBundle(Bundle intent) {
+
+ if (card != null) {
+ intent.putString(TangemCardExtensionsKt.EXTRA_TANGEM_CARD_UID, card.getUID());
+ intent.putBundle(TangemCardExtensionsKt.EXTRA_TANGEM_CARD, TangemCardExtensionsKt.getAsBundle(card));
+ }
+
+ if (coinData != null) {
+ intent.putBundle(Constant.EXTRA_BLOCKCHAIN_DATA, coinData.asBundle());
+ }
+
+ intent.putString("Error", error);
+ intent.putString("Message", message);
+ }
+
public void saveToIntent(Intent intent) {
if (card != null) {
@@ -148,7 +164,6 @@ public class TangemContext {
intent.putExtra("Error", error);
intent.putExtra("Message", message);
-
}
public String getString(int stringId) {
diff --git a/app/src/main/res/layout/activity_loaded_wallet.xml b/app/src/main/res/layout/activity_loaded_wallet.xml
index 1e35662d46..0cc32cadbd 100644
--- a/app/src/main/res/layout/activity_loaded_wallet.xml
+++ b/app/src/main/res/layout/activity_loaded_wallet.xml
@@ -1,21 +1,21 @@
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 48a209311f..713699fd71 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,58 +1,17 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
index 0ba5ab7527..68269087e1 100644
--- a/app/src/main/res/layout/activity_settings.xml
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -20,7 +20,7 @@
diff --git a/app/src/main/res/layout/main_fragment.xml b/app/src/main/res/layout/main_fragment.xml
new file mode 100644
index 0000000000..1d60d30faf
--- /dev/null
+++ b/app/src/main/res/layout/main_fragment.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
index 27013ed373..fd9028cb22 100644
--- a/app/src/main/res/menu/menu_main.xml
+++ b/app/src/main/res/menu/menu_main.xml
@@ -1,25 +1,24 @@
-
-