Add transparent wallet support.
This commit is contained in:
parent
6ee39f1987
commit
f7d4663770
|
@ -0,0 +1,371 @@
|
|||
package cash.z.ecc.android.ui.send
|
||||
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Bundle
|
||||
import android.text.Spanned
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import androidx.core.view.forEach
|
||||
import androidx.core.widget.doAfterTextChanged
|
||||
import cash.z.ecc.android.R
|
||||
import cash.z.ecc.android.databinding.FragmentSendBinding
|
||||
import cash.z.ecc.android.di.viewmodel.activityViewModel
|
||||
import cash.z.ecc.android.ext.*
|
||||
import cash.z.ecc.android.feedback.Report
|
||||
import cash.z.ecc.android.feedback.Report.Funnel.Send
|
||||
import cash.z.ecc.android.feedback.Report.Tap.*
|
||||
import cash.z.ecc.android.ui.base.BaseFragment
|
||||
import cash.z.wallet.sdk.Synchronizer
|
||||
import cash.z.wallet.sdk.block.CompactBlockProcessor.WalletBalance
|
||||
import cash.z.wallet.sdk.ext.*
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SendFragment : BaseFragment<FragmentSendBinding>(),
|
||||
ClipboardManager.OnPrimaryClipChangedListener {
|
||||
override val screen = Report.Screen.SEND
|
||||
|
||||
private var maxZatoshi: Long? = null
|
||||
private var useShieldedFunds: Boolean = true
|
||||
set(value) {
|
||||
// if we're switching to shielded then no need to prevent it
|
||||
// otherwise, do not switch to transparent unless the user agrees to reset the memo
|
||||
if (value || resetMemo()) {
|
||||
field = value
|
||||
sendViewModel.useShieldedFunds = value
|
||||
applyMemo()
|
||||
}
|
||||
}
|
||||
|
||||
val sendViewModel: SendViewModel by activityViewModel()
|
||||
|
||||
val pasteLimit = 20
|
||||
|
||||
override fun inflate(inflater: LayoutInflater): FragmentSendBinding =
|
||||
FragmentSendBinding.inflate(inflater)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding.backButtonHitArea.onClickNavTo(R.id.action_nav_send_to_nav_home) { tapped(SEND_BACK) }
|
||||
binding.sendButtonHitArea.setOnClickListener {
|
||||
onSubmit().also { tapped(SEND_NEXT) }
|
||||
}
|
||||
// binding.textBannerAction.setOnClickListener {
|
||||
// onPaste().also { tapped(SEND_PASTE) }
|
||||
// }
|
||||
// binding.textBannerMessage.setOnClickListener {
|
||||
// onPaste().also { tapped(SEND_PASTE) }
|
||||
// }
|
||||
binding.textPaste.setOnClickListener {
|
||||
onPaste().also { tapped(SEND_PASTE) }
|
||||
}
|
||||
binding.textMax.setOnClickListener {
|
||||
onMax().also { tapped(SEND_MAX) }
|
||||
}
|
||||
|
||||
binding.inputZcashAddress.onEditorActionDone(::onSubmit).also { tapped(SEND_DONE_ADDRESS) }
|
||||
binding.inputZcashAmount.onEditorActionDone(::onSubmit).also { tapped(SEND_DONE_AMOUNT) }
|
||||
|
||||
binding.inputZcashAddress.apply {
|
||||
doAfterTextChanged {
|
||||
val trim = text.toString().trim()
|
||||
if (text.toString() != trim) {
|
||||
binding.inputZcashAddress
|
||||
.findViewById<EditText>(R.id.input_zcash_address).setText(trim)
|
||||
}
|
||||
onAddressChanged(trim)
|
||||
}
|
||||
}
|
||||
|
||||
binding.inputMemo.doAfterTextChanged {
|
||||
sendViewModel.memo = binding.inputMemo.text.toString()
|
||||
updateMemoCount()
|
||||
}
|
||||
|
||||
binding.textLayoutAddress.setEndIconOnClickListener {
|
||||
mainActivity?.maybeOpenScan().also { tapped(SEND_SCAN) }
|
||||
}
|
||||
|
||||
// new behaviors
|
||||
binding.boxShieldedFunds.isClickable = true
|
||||
binding.boxTransparentFunds.isClickable = true
|
||||
useShieldedFunds = true
|
||||
binding.boxShieldedFunds.setOnClickListener {
|
||||
if (!it.isSelected) {
|
||||
useShieldedFunds = true
|
||||
}
|
||||
}
|
||||
binding.boxTransparentFunds.setOnClickListener {
|
||||
if (!it.isSelected) {
|
||||
useShieldedFunds = false
|
||||
}
|
||||
}
|
||||
binding.textSubheader.text.toColoredSpan(R.color.colorPrimaryVariant, "shielded").let { spannable ->
|
||||
val start = binding.textSubheader.text.indexOf("transparent")
|
||||
spannable.setSpan(ForegroundColorSpan(R.color.colorSecondaryVariant.toAppColor()), start, start + "transparent".length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
binding.textSubheader.text = spannable
|
||||
}
|
||||
|
||||
// memo
|
||||
sendViewModel.afterInitFromAddress {
|
||||
binding.textIncludedAddress.text = "sent from ${sendViewModel.fromAddress}"
|
||||
}
|
||||
|
||||
binding.buttonAddMemo.setOnClickListener {
|
||||
onAddMemo((maxZatoshi ?: 0L) > 0L)
|
||||
}
|
||||
|
||||
binding.clearMemo.setOnClickListener {
|
||||
onClearMemo().also { tapped(SEND_MEMO_CLEAR) }
|
||||
}
|
||||
|
||||
binding.checkIncludeAddress.setOnCheckedChangeListener { _, _->
|
||||
onIncludeAddressInMemo(binding.checkIncludeAddress.isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectGroup(group: ViewGroup, isSelected: Boolean) {
|
||||
group.isSelected = isSelected
|
||||
group.forEach {
|
||||
it.isSelected = isSelected
|
||||
}
|
||||
}
|
||||
|
||||
private fun onAddressChanged(address: String) {
|
||||
if (address.length <= pasteLimit) {
|
||||
updateClipboardBanner()
|
||||
} else {
|
||||
sendViewModel.toAddress = binding.inputZcashAddress.text.toString()
|
||||
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()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun onSubmit(unused: EditText? = null) {
|
||||
// TODO: tech debt: improve this logic to be driven by the model rather than this clumsy storage of data in the UI
|
||||
sendViewModel.toAddress = binding.inputZcashAddress.text.toString()
|
||||
binding.inputZcashAmount.convertZecToZatoshi()?.let { sendViewModel.zatoshiAmount = it }
|
||||
sendViewModel.memo = if (useShieldedFunds) binding.inputMemo.text.toString() else ""
|
||||
sendViewModel.validate(maxZatoshi).onFirstWith(resumedScope) {
|
||||
if (it == null) {
|
||||
sendViewModel.funnel(Send.SendPageComplete)
|
||||
mainActivity?.safeNavigate(R.id.action_nav_send_to_send_confirm)
|
||||
} else {
|
||||
resumedScope.launch {
|
||||
binding.textAddressError.text = it
|
||||
delay(3000L)
|
||||
binding.textAddressError.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onMax() {
|
||||
if (maxZatoshi != null) {
|
||||
binding.inputZcashAmount.apply {
|
||||
setText(maxZatoshi.convertZatoshiToZecString(8))
|
||||
postDelayed({
|
||||
requestFocus()
|
||||
setSelection(text?.length ?: 0)
|
||||
}, 10L)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
applyModel()
|
||||
updateClipboardBanner()
|
||||
sendViewModel.synchronizer.balances.collectWith(resumedScope) {
|
||||
onBalanceUpdated(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyModel() {
|
||||
useShieldedFunds = sendViewModel.useShieldedFunds
|
||||
if (sendViewModel.zatoshiAmount > 0L) {
|
||||
sendViewModel.zatoshiAmount.convertZatoshiToZecString(8).let { amount ->
|
||||
binding.inputZcashAmount.setText(amount)
|
||||
}
|
||||
} else {
|
||||
binding.inputZcashAmount.setText(null)
|
||||
}
|
||||
binding.inputZcashAddress.setText(sendViewModel.toAddress)
|
||||
applyMemo()
|
||||
}
|
||||
|
||||
fun applyMemo() {
|
||||
if (sendViewModel.isMemoAdded) {
|
||||
binding.groupMemo.visibility = View.VISIBLE
|
||||
binding.buttonAddMemo.visibility = View.GONE
|
||||
} else {
|
||||
binding.groupMemo.visibility = View.GONE
|
||||
binding.buttonAddMemo.visibility = View.VISIBLE
|
||||
}
|
||||
selectGroup(binding.boxShieldedFunds, sendViewModel.useShieldedFunds)
|
||||
selectGroup(binding.boxTransparentFunds, !sendViewModel.useShieldedFunds)
|
||||
|
||||
binding.inputMemo.setText(sendViewModel.memo)
|
||||
binding.checkIncludeAddress.isChecked = sendViewModel.includeFromAddress
|
||||
binding.textIncludedAddress.goneIf(!sendViewModel.useShieldedFunds || !sendViewModel.includeFromAddress || !sendViewModel.isMemoAdded)
|
||||
}
|
||||
|
||||
private fun onBalanceUpdated(balance: WalletBalance) {
|
||||
val zecString= balance.availableZatoshi.coerceAtLeast(0L).convertZatoshiToZecString(8)
|
||||
binding.textLayoutAmount.helperText =
|
||||
"You have $zecString available"
|
||||
binding.textShieldedFundsAmount.text = "\$${zecString}"
|
||||
maxZatoshi = (balance.availableZatoshi - ZcashSdk.MINERS_FEE_ZATOSHI).coerceAtLeast(0L)
|
||||
}
|
||||
|
||||
override fun onPrimaryClipChanged() {
|
||||
twig("clipboard changed!")
|
||||
updateClipboardBanner()
|
||||
}
|
||||
|
||||
private fun updateClipboardBanner() {
|
||||
val invalidAddressOnClipboard = loadAddressFromClipboard() == null
|
||||
val hidePaste = invalidAddressOnClipboard || (binding.inputZcashAddress.text ?: "").length >= pasteLimit - 1
|
||||
binding.textPaste.goneIf(hidePaste)
|
||||
binding.textLayoutAddress.helperText =
|
||||
"${if (hidePaste) "E" else "Paste or e"}nter a valid Zcash address"
|
||||
binding.textLayoutAddress.setHelperTextColor(ColorStateList.valueOf(R.color.text_light_dimmed.toAppColor()))
|
||||
}
|
||||
|
||||
private fun onAddMemo(hasShieldedFunds: Boolean) {
|
||||
if (!useShieldedFunds) {
|
||||
//TODO: track dialog reference
|
||||
val builder = MaterialAlertDialogBuilder(mainActivity)
|
||||
.setTitle("Shielded Transaction Required")
|
||||
.setMessage("Memos are not supported for transparent transactions. To add a memo, you must send shielded funds.")
|
||||
.setCancelable(true)
|
||||
.setPositiveButton("Ok") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
if (hasShieldedFunds) {
|
||||
builder.setNegativeButton("Switch to Shielded") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
useShieldedFunds = true
|
||||
onAddMemo(hasShieldedFunds)
|
||||
}
|
||||
}
|
||||
builder.show()
|
||||
} else {
|
||||
sendViewModel.isMemoAdded = true
|
||||
applyMemo()
|
||||
binding.inputMemo.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onClearMemo() {
|
||||
sendViewModel.isMemoAdded = false
|
||||
binding.inputMemo.setText("")
|
||||
sendViewModel.memo = ""
|
||||
binding.groupMemo.visibility = View.GONE
|
||||
binding.buttonAddMemo.visibility = View.VISIBLE
|
||||
binding.textIncludedAddress.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun resetMemo(): Boolean {
|
||||
if (sendViewModel.memo.isNullOrEmpty()) {
|
||||
onClearMemo()
|
||||
return true
|
||||
} else {
|
||||
MaterialAlertDialogBuilder(mainActivity)
|
||||
.setTitle("Are you sure?")
|
||||
.setMessage("Memos are not supported for transparent transactions. If you switch to transparent funds, your memo will be lost.")
|
||||
.setCancelable(true)
|
||||
.setPositiveButton("Clear Memo") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
onClearMemo()
|
||||
useShieldedFunds = false
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private fun onIncludeAddressInMemo(checked: Boolean) {
|
||||
binding.textIncludedAddress.goneIf(!checked)
|
||||
sendViewModel.includeFromAddress = checked
|
||||
if (checked) {
|
||||
tapped(SEND_MEMO_INCLUDE)
|
||||
// getString(R.string.send_memo_included_message)
|
||||
} else {
|
||||
tapped(SEND_MEMO_EXCLUDE)
|
||||
// getString(R.string.send_memo_excluded_message)
|
||||
}
|
||||
updateMemoCount()
|
||||
}
|
||||
|
||||
private fun updateMemoCount() {
|
||||
var count = sendViewModel.createMemoToSend().length
|
||||
binding.textMemoCount.text = "$count/512"
|
||||
val color = if (count > 512) R.color.zcashRed else R.color.text_light_dimmed
|
||||
binding.textMemoCount.setTextColor(color.toAppColor())
|
||||
}
|
||||
|
||||
private fun onPaste() {
|
||||
mainActivity?.clipboard?.let { clipboard ->
|
||||
if (clipboard.hasPrimaryClip()) {
|
||||
binding.inputZcashAddress.setText(clipboard.text())
|
||||
}
|
||||
}
|
||||
binding.textPaste.visibility = View.GONE
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="false" android:color="@color/background_unselected_stroke"/>
|
||||
<item android:state_pressed="false" android:color="@color/colorPrimary"/>
|
||||
<item android:state_pressed="true" android:color="@color/colorPrimaryVariant" />
|
||||
</selector>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="false" android:color="@color/background_unselected_stroke"/>
|
||||
<item android:state_pressed="false" android:color="@color/colorSecondary"/>
|
||||
<item android:state_pressed="true" android:color="@color/colorSecondaryVariant" />
|
||||
</selector>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="false" android:color="@color/colorPrimaryVariant"/>
|
||||
<item android:state_pressed="false" android:color="@color/colorPrimary"/>
|
||||
<item android:state_pressed="true" android:color="@color/colorPrimaryVariant" />
|
||||
</selector>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="false" android:color="@color/colorSecondaryVariant"/>
|
||||
<item android:state_pressed="false" android:color="@color/colorSecondary"/>
|
||||
<item android:state_pressed="true" android:color="@color/colorSecondaryVariant" />
|
||||
</selector>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="false" android:color="@color/text_light_dimmed"/>
|
||||
<item android:state_pressed="false" android:color="@color/text_light"/>
|
||||
<item android:state_pressed="true" android:color="@color/text_light_dimmed" />
|
||||
</selector>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="0dp" />
|
||||
<stroke android:width="1dp" android:color="@color/selector_button_border_primary"/>
|
||||
</shape>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="0dp" />
|
||||
<stroke android:width="1dp" android:color="@color/selector_button_border_secondary"/>
|
||||
</shape>
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M13,7h-2v4L7,11v2h4v4h2v-4h4v-2h-4L13,7zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
|
||||
</vector>
|
|
@ -0,0 +1,480 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/scroll_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
android:fillViewport="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/background_home"
|
||||
android:paddingBottom="500dp">
|
||||
|
||||
<!-- Back Button -->
|
||||
<ImageView
|
||||
android:id="@+id/back_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.05"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.065"
|
||||
app:srcCompat="@drawable/ic_arrow_back_black_24dp"
|
||||
app:tint="@color/text_light" />
|
||||
|
||||
<View
|
||||
android:id="@+id/back_button_hit_area"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:clickable="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.01"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.045" />
|
||||
|
||||
<!-- send Button -->
|
||||
<ImageView
|
||||
android:id="@+id/send_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.95"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.065"
|
||||
app:srcCompat="@drawable/ic_send_24dp"
|
||||
app:tint="@color/text_light" />
|
||||
|
||||
<View
|
||||
android:id="@+id/send_button_hit_area"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:clickable="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.99"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.045" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_header"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:autoSizeTextType="uniform"
|
||||
android:fontFamily="sans-serif-thin"
|
||||
android:maxLines="1"
|
||||
|
||||
android:text="We need some details!"
|
||||
android:textColor="@color/text_light"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="@+id/text_layout_amount"
|
||||
app:layout_constraintStart_toStartOf="@+id/text_layout_amount"
|
||||
app:layout_constraintTop_toBottomOf="@id/back_button_hit_area" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_subheader"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
|
||||
android:autoSizeTextType="uniform"
|
||||
android:maxLines="2"
|
||||
|
||||
android:text="This wallet has both a shielded and a transparent address.\nPlease fill out all the transaction details and click send above."
|
||||
android:textColor="@color/text_light_dimmed"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toEndOf="@+id/text_layout_amount"
|
||||
app:layout_constraintStart_toStartOf="@+id/text_layout_amount"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_header" />
|
||||
|
||||
<!-- Shielded Funds Box -->
|
||||
<LinearLayout
|
||||
android:id="@+id/box_shielded_funds"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:background="@drawable/background_button_square_primary"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="12dp"
|
||||
android:paddingTop="8dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/box_transparent_funds"
|
||||
app:layout_constraintStart_toStartOf="@id/text_layout_amount"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_subheader">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_shielded_funds_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="Shielded Funds"
|
||||
android:textColor="@color/selector_button_text_primary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_shielded_funds_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="8dp"
|
||||
android:autoSizeTextType="uniform"
|
||||
android:fontFamily="@font/zboto"
|
||||
android:maxLines="1"
|
||||
android:text="$20.94"
|
||||
android:textColor="@color/selector_selectable_text_light"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Transparent Funds Box -->
|
||||
<LinearLayout
|
||||
android:id="@+id/box_transparent_funds"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="2dp"
|
||||
android:background="@drawable/background_button_square_secondary"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="12dp"
|
||||
android:paddingTop="8dp"
|
||||
app:layout_constraintEnd_toEndOf="@id/text_layout_address"
|
||||
app:layout_constraintStart_toEndOf="@id/box_shielded_funds"
|
||||
app:layout_constraintTop_toTopOf="@id/box_shielded_funds">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_transparent_funds_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="Transparent Funds"
|
||||
android:textColor="@color/selector_button_text_secondary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_transparent_funds_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="8dp"
|
||||
android:autoSizeTextType="uniform"
|
||||
android:fontFamily="@font/zboto"
|
||||
android:maxLines="1"
|
||||
android:text="$12.42785435"
|
||||
android:textColor="@color/selector_selectable_text_light"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Input: Amount -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/text_layout_amount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:hint="Amount"
|
||||
android:theme="@style/Zcash.Overlay.TextInputLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/box_shielded_funds"
|
||||
app:layout_constraintWidth_percent="0.84"
|
||||
tools:helperText="You have 23.23 ZEC available">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_zcash_amount"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="numberDecimal"
|
||||
android:maxLength="20"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/text_light"
|
||||
android:textColorHint="@color/text_light_dimmed" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!-- Input: Address -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/text_layout_address"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:hint="To"
|
||||
android:theme="@style/Zcash.Overlay.TextInputLayout"
|
||||
app:endIconDrawable="@drawable/ic_qrcode_24dp"
|
||||
app:endIconMode="custom"
|
||||
app:helperText="Paste or enter a valid Zcash address"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_layout_amount"
|
||||
app:layout_constraintWidth_percent="0.84">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input_zcash_address"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:maxLength="255"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/text_light"
|
||||
android:textColorHint="@color/text_light_dimmed" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/button_add_memo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:drawablePadding="8dp"
|
||||
android:drawableStart="@drawable/ic_add_circle_outline_24dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingTop="16dp"
|
||||
android:text="Add Memo"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@color/text_light"
|
||||
app:layout_constraintStart_toStartOf="@id/text_layout_address"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_layout_address"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_max"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:fontFamily="@font/inconsolata"
|
||||
android:padding="16dp"
|
||||
android:text="MAX"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@id/text_layout_amount"
|
||||
app:layout_constraintEnd_toEndOf="@id/text_layout_amount"
|
||||
app:layout_constraintTop_toTopOf="@id/text_layout_amount" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_address_error"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoSizeTextType="uniform"
|
||||
android:fontFamily="@font/inconsolata"
|
||||
android:gravity="center"
|
||||
android:maxLines="2"
|
||||
android:paddingEnd="4dp"
|
||||
android:paddingStart="4dp"
|
||||
android:textColor="@color/zcashRed"
|
||||
android:textSize="12dp"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/back_button"
|
||||
app:layout_constraintEnd_toStartOf="@id/send_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/back_button"
|
||||
tools:text="Please enter short msg" />
|
||||
|
||||
<!-- Scan QR code -->
|
||||
<ImageView
|
||||
android:id="@+id/image_scan_qr"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="24dp"
|
||||
android:paddingEnd="1dp"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingTop="10dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/text_layout_address"
|
||||
app:layout_constraintEnd_toEndOf="@id/text_layout_address"
|
||||
app:layout_constraintTop_toTopOf="@id/text_layout_address"
|
||||
app:srcCompat="@drawable/ic_qrcode_24dp"
|
||||
app:tint="@color/zcashWhite" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_paste"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:fontFamily="@font/inconsolata"
|
||||
android:padding="16dp"
|
||||
android:text="PASTE"
|
||||
android:textColor="@color/text_light_dimmed"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@id/text_layout_address"
|
||||
app:layout_constraintEnd_toEndOf="@id/text_layout_address"
|
||||
app:layout_constraintHorizontal_bias="0.84"
|
||||
app:layout_constraintStart_toStartOf="@id/text_layout_address"
|
||||
app:layout_constraintTop_toTopOf="@id/text_layout_address"
|
||||
app:layout_constraintVertical_bias="0.3" />
|
||||
|
||||
<!-- <com.google.android.material.button.MaterialButton-->
|
||||
<!-- android:id="@+id/button_next"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginTop="16dp"-->
|
||||
<!-- android:text="Next"-->
|
||||
<!-- android:textColor="@color/text_dark"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="@+id/text_layout_address"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@+id/text_layout_amount" />-->
|
||||
|
||||
<!-- -->
|
||||
<!-- Banner -->
|
||||
<!-- -->
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/text_banner_message"-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:background="@drawable/background_banner"-->
|
||||
<!-- android:elevation="6dp"-->
|
||||
<!-- android:paddingBottom="8dp"-->
|
||||
<!-- android:paddingStart="16dp"-->
|
||||
<!-- android:paddingTop="8dp"-->
|
||||
<!-- android:text="Address on clipboard!"-->
|
||||
<!-- android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"-->
|
||||
<!-- android:textColor="@color/text_light"-->
|
||||
<!-- android:visibility="invisible"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="@+id/text_layout_address"-->
|
||||
<!-- app:layout_constraintHorizontal_bias="0.0"-->
|
||||
<!-- app:layout_constraintStart_toStartOf="@+id/text_layout_address"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@id/back_button_hit_area" />-->
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/text_banner_action"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginEnd="16dp"-->
|
||||
<!-- android:elevation="6dp"-->
|
||||
<!-- android:text="Paste"-->
|
||||
<!-- android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"-->
|
||||
<!-- android:textColor="@color/colorPrimary"-->
|
||||
<!-- android:visibility="invisible"-->
|
||||
<!-- app:layout_constraintBaseline_toBaselineOf="@id/text_banner_message"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="@id/text_banner_message" />-->
|
||||
|
||||
|
||||
<!-- -->
|
||||
<!-- Memo -->
|
||||
<!-- -->
|
||||
|
||||
|
||||
<View
|
||||
android:id="@+id/background_memo"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:background="@drawable/background_banner"
|
||||
android:elevation="6dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_percent="0.24"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_layout_address"
|
||||
app:layout_constraintWidth_percent="0.84" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/input_memo"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:elevation="6dp"
|
||||
android:gravity="top"
|
||||
android:hint="Add a memo here"
|
||||
android:imeActionLabel="add memo"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="textMultiLine"
|
||||
android:maxLength="512"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingEnd="32dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
android:scrollbars="vertical"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:textColor="@color/text_light"
|
||||
app:layout_constraintBottom_toTopOf="@id/text_included_address"
|
||||
app:layout_constraintEnd_toEndOf="@id/background_memo"
|
||||
app:layout_constraintStart_toStartOf="@id/background_memo"
|
||||
app:layout_constraintTop_toTopOf="@id/background_memo"
|
||||
tools:text="this\nis\nsome\ntext\nthat\nspans\nmany\nlines" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_included_address"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="6dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingStart="16dp"
|
||||
android:textColor="@color/text_light_dimmed"
|
||||
app:layout_constraintBottom_toBottomOf="@id/background_memo"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintWidth_percent="0.84"
|
||||
tools:text="sent from z23lk4jjl2k3jl43kkj542l3kl4hj2l3k1j41l2kjk423lkj423lklhk2jrhiuhrh2j4hh2hkj23hkj4" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/clear_memo"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:elevation="6dp"
|
||||
android:src="@drawable/ic_close_black_24dp"
|
||||
app:layout_constraintEnd_toEndOf="@id/background_memo"
|
||||
app:layout_constraintTop_toTopOf="@id/background_memo"
|
||||
app:tint="@color/text_light" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/check_include_address"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:padding="0dp"
|
||||
android:text="Include your sending address in memo"
|
||||
app:layout_constraintStart_toStartOf="@+id/background_memo"
|
||||
app:layout_constraintTop_toBottomOf="@+id/background_memo" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_memo_count"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:autoSizeTextType="uniform"
|
||||
android:maxLines="2"
|
||||
android:text="0/512"
|
||||
android:textColor="@color/text_light_dimmed"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toEndOf="@id/background_memo"
|
||||
app:layout_constraintTop_toBottomOf="@id/background_memo" />
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/text_info_shielded"-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginTop="16dp"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:text="Your transaction is shielded and your address is not available to recipient."-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="@id/background_memo"-->
|
||||
<!-- app:layout_constraintStart_toStartOf="@id/background_memo"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@id/check_include_address" />-->
|
||||
|
||||
<!-- <androidx.constraintlayout.widget.Group-->
|
||||
<!-- android:id="@+id/group_banner"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:visibility="visible"-->
|
||||
<!-- app:constraint_referenced_ids="text_banner_message, text_banner_action"-->
|
||||
<!-- tools:visibility="visible" />-->
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_memo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:constraint_referenced_ids="check_include_address, background_memo, input_memo, clear_memo, text_memo_count"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
|
@ -8,8 +8,11 @@
|
|||
<!-- colors here should map to a material design value -->
|
||||
|
||||
<color name="colorPrimary">@color/zcashYellow</color>
|
||||
<color name="colorPrimaryVariant">#80FFB900</color>
|
||||
<color name="colorPrimaryMedium">#805E08</color>
|
||||
<color name="colorPrimaryDark">#4D3805</color>
|
||||
<color name="colorSecondary">#4A90E2</color>
|
||||
<color name="colorSecondaryVariant">#804A90E2</color>
|
||||
<color name="colorAccent">#A1A1A1</color>
|
||||
<color name="colorSurface">@color/text_light</color>
|
||||
<color name="colorOnSurface">@color/background_banner</color>
|
||||
|
@ -59,6 +62,7 @@
|
|||
|
||||
<color name="background_banner">@color/zcashBlack_dark</color>
|
||||
<color name="background_banner_stroke">#282828</color>
|
||||
<color name="background_unselected_stroke">@color/zcashBlack_54</color>
|
||||
<color name="scan_overlay_background">@color/zcashBlack_87</color>
|
||||
<color name="spacer">#1FBB666A</color>
|
||||
<color name="text_send_amount_disabled">@color/text_light</color>
|
||||
|
|
Loading…
Reference in New Issue