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 @@ - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/main_graph.xml b/app/src/main/res/navigation/main_graph.xml new file mode 100644 index 0000000000..5a8ad7b3a9 --- /dev/null +++ b/app/src/main/res/navigation/main_graph.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dceb1d6cdd..35a6a77e84 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -58,6 +58,8 @@ Cardano + Common + Manual editing Fee Settings Encryption modes @@ -115,7 +117,7 @@ There is a new application version: %1$s Update - + The wallet is empty No compatible wallets installed Please wait while previous transaction is confirmed in blockchain @@ -217,6 +219,7 @@ PIN2 is required to sign the payment Not enough funds Service unavailable + You have a risk of delaying transaction Wallet hasn\'t been yet created diff --git a/app/src/main/res/values/strings_untranslatable.xml b/app/src/main/res/values/strings_untranslatable.xml index 13279d3f9c..7783a7ef97 100644 --- a/app/src/main/res/values/strings_untranslatable.xml +++ b/app/src/main/res/values/strings_untranslatable.xml @@ -23,4 +23,9 @@ com.tangem.data.LogFileProvider Can\'t create CoinEngine! + category_common + manual_editing_fee + select_nodes + encryption_modes + diff --git a/app/src/main/res/xml/pref_main.xml b/app/src/main/res/xml/pref_main.xml index ff16adfc67..9227025a9c 100644 --- a/app/src/main/res/xml/pref_main.xml +++ b/app/src/main/res/xml/pref_main.xml @@ -1,20 +1,25 @@ - + + + - \ No newline at end of file diff --git a/app/src/tangemAccess/java/com/tangem/ui/ConfirmTransactionActivity.kt b/app/src/tangemAccess/java/com/tangem/ui/ConfirmTransactionActivity.kt index 60921bcef7..88b5d56871 100644 --- a/app/src/tangemAccess/java/com/tangem/ui/ConfirmTransactionActivity.kt +++ b/app/src/tangemAccess/java/com/tangem/ui/ConfirmTransactionActivity.kt @@ -2,40 +2,49 @@ package com.tangem.ui import android.app.Activity import android.content.Intent +import android.content.SharedPreferences import android.nfc.NfcAdapter import android.nfc.Tag import android.os.Build import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity +import android.preference.PreferenceManager import android.text.Editable import android.text.Html import android.text.TextWatcher import android.view.KeyEvent import android.view.View import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.tangem.App import com.tangem.Constant -import com.tangem.data.Blockchain -import com.tangem.wallet.CoinEngine -import com.tangem.wallet.CoinEngineFactory -import com.tangem.wallet.TangemContext -import com.tangem.ui.event.TransactionFinishWithError import com.tangem.card_android.android.nfc.NfcLifecycleObserver import com.tangem.card_android.android.reader.NfcManager +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_common.data.TangemCard +import com.tangem.data.Blockchain +import com.tangem.di.ToastHelper +import com.tangem.ui.activity.PinRequestActivity +import com.tangem.ui.activity.SignTransactionActivity +import com.tangem.ui.event.TransactionFinishWithError import com.tangem.util.UtilHelper +import com.tangem.wallet.CoinEngine +import com.tangem.wallet.CoinEngineFactory import com.tangem.wallet.R +import com.tangem.wallet.TangemContext +import kotlinx.android.synthetic.tangemAccess.activity_confirm_transaction.* import org.greenrobot.eventbus.EventBus import java.io.IOException import java.util.* -import com.tangem.card_android.data.EXTRA_TANGEM_CARD -import com.tangem.card_android.data.EXTRA_TANGEM_CARD_UID -import com.tangem.ui.activity.PinRequestActivity -import com.tangem.ui.activity.SignTransactionActivity -import kotlinx.android.synthetic.tangemAccess.activity_confirm_transaction.* +import javax.inject.Inject class ConfirmTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { + @Inject + internal lateinit var toastHelper: ToastHelper + + private lateinit var sp: SharedPreferences private lateinit var nfcManager: NfcManager private lateinit var ctx: TangemContext private lateinit var amount: CoinEngine.Amount @@ -49,6 +58,10 @@ class ConfirmTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallbac super.onCreate(savedInstanceState) setContentView(R.layout.activity_confirm_transaction) + App.toastHelperComponent.inject(this) + + sp = PreferenceManager.getDefaultSharedPreferences(this) + nfcManager = NfcManager(this, this) lifecycle.addObserver(NfcLifecycleObserver(nfcManager)) @@ -95,6 +108,8 @@ class ConfirmTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallbac rgFee.visibility = View.INVISIBLE } + etFee.isEnabled = sp.getBoolean(getString(R.string.pref_manual_editing_fee), false) + // set listeners rgFee.setOnCheckedChangeListener { _, checkedId -> doSetFee(checkedId) } etFee.addTextChangedListener(object : TextWatcher { @@ -114,6 +129,9 @@ class ConfirmTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallbac } else tvFeeEquivalent.error = null + if (sp.getBoolean(getString(R.string.pref_manual_editing_fee), false)) + toastHelper.showSingleToast(this@ConfirmTransactionActivity, getString(R.string.risk_delaying)) + } catch (e: Exception) { e.printStackTrace() tvFeeEquivalent.text = "" diff --git a/app/src/tangemAccess/res/layout/activity_confirm_transaction.xml b/app/src/tangemAccess/res/layout/activity_confirm_transaction.xml index 8e8c0c19e0..a3e049834c 100644 --- a/app/src/tangemAccess/res/layout/activity_confirm_transaction.xml +++ b/app/src/tangemAccess/res/layout/activity_confirm_transaction.xml @@ -2,6 +2,7 @@ + android:layout_height="match_parent"> + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintWidth_min="150dp" + tools:text="1.34343434343443434343434" /> + android:layout_height="match_parent"> + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintWidth_min="150dp" + tools:text="1.34343434343443434343434" />