2019-12-23 11:16:00 -08:00
|
|
|
package cash.z.ecc.android.ui.send
|
|
|
|
|
|
|
|
import android.content.ClipboardManager
|
|
|
|
import android.content.Context
|
2020-01-09 23:53:16 -08:00
|
|
|
import android.content.res.ColorStateList
|
2019-12-23 11:16:00 -08:00
|
|
|
import android.os.Bundle
|
2020-01-10 10:58:10 -08:00
|
|
|
import android.util.Log
|
2019-12-23 11:16:00 -08:00
|
|
|
import android.view.LayoutInflater
|
|
|
|
import android.view.View
|
2020-01-08 00:45:45 -08:00
|
|
|
import android.widget.EditText
|
2020-01-09 23:53:16 -08:00
|
|
|
import androidx.core.widget.doAfterTextChanged
|
2019-12-23 11:16:00 -08:00
|
|
|
import cash.z.ecc.android.R
|
|
|
|
import cash.z.ecc.android.databinding.FragmentSendAddressBinding
|
2020-01-08 00:45:45 -08:00
|
|
|
import cash.z.ecc.android.di.viewmodel.activityViewModel
|
|
|
|
import cash.z.ecc.android.ext.*
|
2019-12-23 11:16:00 -08:00
|
|
|
import cash.z.ecc.android.ui.base.BaseFragment
|
2020-01-09 23:53:16 -08:00
|
|
|
import cash.z.wallet.sdk.Synchronizer
|
|
|
|
import cash.z.wallet.sdk.block.CompactBlockProcessor.WalletBalance
|
2020-01-08 00:45:45 -08:00
|
|
|
import cash.z.wallet.sdk.ext.*
|
|
|
|
import kotlinx.coroutines.delay
|
|
|
|
import kotlinx.coroutines.launch
|
2019-12-23 11:16:00 -08:00
|
|
|
|
|
|
|
class SendAddressFragment : BaseFragment<FragmentSendAddressBinding>(),
|
|
|
|
ClipboardManager.OnPrimaryClipChangedListener {
|
|
|
|
|
2020-01-09 23:53:16 -08:00
|
|
|
private var maxZatoshi: Long? = null
|
|
|
|
|
2020-01-08 00:45:45 -08:00
|
|
|
val sendViewModel: SendViewModel by activityViewModel()
|
2020-01-05 21:01:06 -08:00
|
|
|
|
2019-12-23 11:16:00 -08:00
|
|
|
override fun inflate(inflater: LayoutInflater): FragmentSendAddressBinding =
|
|
|
|
FragmentSendAddressBinding.inflate(inflater)
|
|
|
|
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
|
|
super.onViewCreated(view, savedInstanceState)
|
2020-01-09 23:53:16 -08:00
|
|
|
binding.backButtonHitArea.onClickNavTo(R.id.action_nav_send_address_to_nav_home)
|
2019-12-23 11:16:00 -08:00
|
|
|
binding.buttonNext.setOnClickListener {
|
2020-01-08 00:45:45 -08:00
|
|
|
onSubmit()
|
2019-12-23 11:16:00 -08:00
|
|
|
}
|
|
|
|
binding.textBannerAction.setOnClickListener {
|
|
|
|
onPaste()
|
|
|
|
}
|
|
|
|
binding.textBannerMessage.setOnClickListener {
|
|
|
|
onPaste()
|
|
|
|
}
|
2020-01-09 23:53:16 -08:00
|
|
|
binding.textMax.setOnClickListener {
|
|
|
|
onMax()
|
|
|
|
}
|
2020-01-08 00:45:45 -08:00
|
|
|
|
|
|
|
// Apply View Model
|
|
|
|
if (sendViewModel.zatoshiAmount > 0L) {
|
|
|
|
sendViewModel.zatoshiAmount.convertZatoshiToZecString(8).let { amount ->
|
|
|
|
binding.inputZcashAmount.setText(amount)
|
2019-12-23 11:16:00 -08:00
|
|
|
}
|
2020-01-08 00:45:45 -08:00
|
|
|
} else {
|
|
|
|
binding.inputZcashAmount.setText(null)
|
|
|
|
}
|
2020-01-09 23:53:16 -08:00
|
|
|
if (!sendViewModel.toAddress.isNullOrEmpty()) {
|
2020-01-08 00:45:45 -08:00
|
|
|
binding.inputZcashAddress.setText(sendViewModel.toAddress)
|
|
|
|
} else {
|
|
|
|
binding.inputZcashAddress.setText(null)
|
2019-12-23 11:16:00 -08:00
|
|
|
}
|
2020-01-08 00:45:45 -08:00
|
|
|
|
|
|
|
binding.inputZcashAddress.onEditorActionDone(::onSubmit)
|
2020-01-09 23:53:16 -08:00
|
|
|
binding.inputZcashAmount.onEditorActionDone(::onSubmit)
|
2020-01-08 00:45:45 -08:00
|
|
|
|
2020-01-09 23:53:16 -08:00
|
|
|
binding.inputZcashAddress.apply {
|
|
|
|
doAfterTextChanged {
|
|
|
|
onAddressChanged(text.toString())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
binding.textLayoutAddress.setEndIconOnClickListener {
|
|
|
|
mainActivity?.maybeOpenScan()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun onAddressChanged(address: String) {
|
|
|
|
resumedScope.launch {
|
|
|
|
var type = when (sendViewModel.validateAddress(address)) {
|
|
|
|
is Synchronizer.AddressType.Transparent -> "This is a valid transparent address" to R.color.zcashGreen
|
|
|
|
is Synchronizer.AddressType.Shielded -> "This is a valid shielded address" to R.color.zcashGreen
|
|
|
|
is Synchronizer.AddressType.Invalid -> "This address appears to be invalid" to R.color.zcashRed
|
|
|
|
}
|
|
|
|
if (address == sendViewModel.synchronizer.getAddress()) type =
|
|
|
|
"Warning, this appears to be your address!" to R.color.zcashRed
|
|
|
|
binding.textLayoutAddress.helperText = type.first
|
|
|
|
binding.textLayoutAddress.setHelperTextColor(ColorStateList.valueOf(type.second.toAppColor()))
|
|
|
|
}
|
2019-12-23 11:16:00 -08:00
|
|
|
}
|
|
|
|
|
2020-01-08 00:45:45 -08:00
|
|
|
|
|
|
|
private fun onSubmit(unused: EditText? = null) {
|
2020-01-05 21:01:06 -08:00
|
|
|
sendViewModel.toAddress = binding.inputZcashAddress.text.toString()
|
2020-01-08 00:45:45 -08:00
|
|
|
binding.inputZcashAmount.convertZecToZatoshi()?.let { sendViewModel.zatoshiAmount = it }
|
2020-01-09 23:53:16 -08:00
|
|
|
sendViewModel.validate(maxZatoshi).onFirstWith(resumedScope) {
|
2020-01-08 00:45:45 -08:00
|
|
|
if (it == null) {
|
|
|
|
mainActivity?.navController?.navigate(R.id.action_nav_send_address_to_send_memo)
|
|
|
|
} else {
|
|
|
|
resumedScope.launch {
|
|
|
|
binding.textAddressError.text = it
|
|
|
|
delay(1500L)
|
2020-01-09 23:53:16 -08:00
|
|
|
binding.textAddressError.text = ""
|
2020-01-08 00:45:45 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-12-23 11:16:00 -08:00
|
|
|
}
|
|
|
|
|
2020-01-09 23:53:16 -08:00
|
|
|
private fun onMax() {
|
|
|
|
if (maxZatoshi != null) {
|
|
|
|
binding.inputZcashAmount.apply {
|
|
|
|
setText(maxZatoshi.convertZatoshiToZecString())
|
|
|
|
postDelayed({
|
|
|
|
requestFocus()
|
|
|
|
setSelection(text?.length ?: 0)
|
|
|
|
}, 10L)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-23 11:16:00 -08:00
|
|
|
override fun onAttach(context: Context) {
|
|
|
|
super.onAttach(context)
|
|
|
|
mainActivity?.clipboard?.addPrimaryClipChangedListener(this)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onDetach() {
|
|
|
|
super.onDetach()
|
|
|
|
mainActivity?.clipboard?.removePrimaryClipChangedListener(this)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onResume() {
|
|
|
|
super.onResume()
|
|
|
|
updateClipboardBanner()
|
2020-01-09 23:53:16 -08:00
|
|
|
sendViewModel.synchronizer.balances.collectWith(resumedScope) {
|
|
|
|
onBalanceUpdated(it)
|
|
|
|
}
|
|
|
|
binding.inputZcashAddress.text.toString().let {
|
|
|
|
if (!it.isNullOrEmpty()) onAddressChanged(it)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun onBalanceUpdated(balance: WalletBalance) {
|
|
|
|
binding.textLayoutAmount.helperText =
|
|
|
|
"You have ${balance.availableZatoshi.convertZatoshiToZecString(8)} available"
|
|
|
|
maxZatoshi = balance.availableZatoshi - ZcashSdk.MINERS_FEE_ZATOSHI
|
2019-12-23 11:16:00 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onPrimaryClipChanged() {
|
|
|
|
twig("clipboard changed!")
|
|
|
|
updateClipboardBanner()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun updateClipboardBanner() {
|
|
|
|
binding.groupBanner.goneIf(loadAddressFromClipboard() == null)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun onPaste() {
|
|
|
|
mainActivity?.clipboard?.let { clipboard ->
|
|
|
|
if (clipboard.hasPrimaryClip()) {
|
|
|
|
binding.inputZcashAddress.setText(clipboard.text())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun loadAddressFromClipboard(): String? {
|
|
|
|
mainActivity?.clipboard?.apply {
|
|
|
|
if (hasPrimaryClip()) {
|
|
|
|
text()?.let { text ->
|
|
|
|
if (text.startsWith("zs") && text.length > 70) {
|
|
|
|
return@loadAddressFromClipboard text.toString()
|
|
|
|
}
|
|
|
|
// treat t-addrs differently in the future
|
|
|
|
if (text.startsWith("t1") && text.length > 32) {
|
|
|
|
return@loadAddressFromClipboard text.toString()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun ClipboardManager.text(): CharSequence =
|
|
|
|
primaryClip!!.getItemAt(0).coerceToText(mainActivity)
|
2020-01-05 21:01:06 -08:00
|
|
|
}
|