129 lines
5.7 KiB
Kotlin
129 lines
5.7 KiB
Kotlin
package cash.z.ecc.android.ui.send
|
|
|
|
import android.content.Context
|
|
import android.os.Bundle
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import androidx.lifecycle.lifecycleScope
|
|
import cash.z.ecc.android.R
|
|
import cash.z.ecc.android.databinding.FragmentSendFinalBinding
|
|
import cash.z.ecc.android.di.viewmodel.activityViewModel
|
|
import cash.z.ecc.android.ext.goneIf
|
|
import cash.z.ecc.android.feedback.Report
|
|
import cash.z.ecc.android.feedback.Report.Tap.*
|
|
import cash.z.ecc.android.ui.base.BaseFragment
|
|
import cash.z.ecc.android.sdk.db.entity.*
|
|
import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString
|
|
import cash.z.ecc.android.sdk.ext.toAbbreviatedAddress
|
|
import cash.z.ecc.android.sdk.ext.twig
|
|
import com.crashlytics.android.Crashlytics
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.flow.flow
|
|
import kotlinx.coroutines.flow.launchIn
|
|
import kotlinx.coroutines.flow.onEach
|
|
import kotlin.random.Random
|
|
|
|
class SendFinalFragment : BaseFragment<FragmentSendFinalBinding>() {
|
|
override val screen = Report.Screen.SEND_FINAL
|
|
|
|
val sendViewModel: SendViewModel by activityViewModel()
|
|
|
|
override fun inflate(inflater: LayoutInflater): FragmentSendFinalBinding =
|
|
FragmentSendFinalBinding.inflate(inflater)
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
super.onViewCreated(view, savedInstanceState)
|
|
binding.buttonNext.setOnClickListener {
|
|
onExit().also { tapped(SEND_FINAL_EXIT) }
|
|
}
|
|
binding.buttonRetry.setOnClickListener {
|
|
onRetry().also { tapped(SEND_FINAL_RETRY) }
|
|
}
|
|
binding.backButtonHitArea.setOnClickListener {
|
|
onExit().also { tapped(SEND_FINAL_CLOSE) }
|
|
}
|
|
binding.textConfirmation.text =
|
|
"Sending ${sendViewModel.zatoshiAmount.convertZatoshiToZecString(8)} ZEC to ${sendViewModel.toAddress.toAbbreviatedAddress()}"
|
|
sendViewModel.memo.trim().isNotEmpty().let { hasMemo ->
|
|
binding.radioIncludeAddress.isChecked = hasMemo
|
|
binding.radioIncludeAddress.goneIf(!hasMemo)
|
|
}
|
|
mainActivity?.preventBackPress(this)
|
|
}
|
|
|
|
override fun onAttach(context: Context) {
|
|
super.onAttach(context)
|
|
mainActivity?.apply {
|
|
sendViewModel.send().onEach {
|
|
onPendingTxUpdated(it)
|
|
}.launchIn(mainActivity?.lifecycleScope!!)
|
|
}
|
|
}
|
|
|
|
override fun onResume() {
|
|
super.onResume()
|
|
flow {
|
|
val max = binding.progressHorizontal.max - 1
|
|
var progress = 0
|
|
while (progress < max) {
|
|
emit(progress)
|
|
delay(Random.nextLong(1000))
|
|
progress++
|
|
}
|
|
}.onEach {
|
|
binding.progressHorizontal.progress = it
|
|
}.launchIn(resumedScope)
|
|
}
|
|
|
|
private fun onPendingTxUpdated(pendingTransaction: PendingTransaction?) {
|
|
try {
|
|
if (pendingTransaction != null) sendViewModel.updateMetrics(pendingTransaction)
|
|
val id = pendingTransaction?.id ?: -1
|
|
var isSending = true
|
|
var isFailure = false
|
|
var step: Report.Funnel.Send? = null
|
|
val message = when {
|
|
pendingTransaction == null -> "Transaction not found".also { step = Report.Funnel.Send.ErrorNotFound }
|
|
pendingTransaction.isMined() -> "Transaction Mined!\n\nSEND COMPLETE".also { isSending = false; step = Report.Funnel.Send.Mined(pendingTransaction.minedHeight) }
|
|
pendingTransaction.isSubmitSuccess() -> "Successfully submitted transaction!\nAwaiting confirmation . . .".also { step = Report.Funnel.Send.Submitted }
|
|
pendingTransaction.isFailedEncoding() -> "ERROR: failed to encode transaction! (id: $id)".also { isSending = false; isFailure = true; step = Report.Funnel.Send.ErrorEncoding(pendingTransaction?.errorCode, pendingTransaction?.errorMessage) }
|
|
pendingTransaction.isFailedSubmit() -> "ERROR: failed to submit transaction! (id: $id)".also { isSending = false; isFailure = true; step = Report.Funnel.Send.ErrorSubmitting(pendingTransaction?.errorCode, pendingTransaction?.errorMessage) }
|
|
pendingTransaction.isCreated() -> "Transaction creation complete!".also { step = Report.Funnel.Send.Created(id) }
|
|
pendingTransaction.isCreating() -> "Creating transaction . . .".also { step = Report.Funnel.Send.Creating }
|
|
else -> "Transaction updated!".also { twig("Unhandled TX state: $pendingTransaction") }
|
|
}
|
|
|
|
sendViewModel.funnel(step)
|
|
|
|
twig("Pending TX (id: ${pendingTransaction?.id} Updated with message: $message")
|
|
binding.textStatus.apply {
|
|
text = "$message"
|
|
}
|
|
binding.backButton.goneIf(!binding.textStatus.text.toString().contains("Awaiting"))
|
|
binding.buttonNext.goneIf((pendingTransaction?.isSubmitSuccess() != true) && (pendingTransaction?.isCreated() != true) && !isFailure)
|
|
binding.buttonNext.text = if (isSending) "Done" else "Finished"
|
|
binding.buttonRetry.goneIf(!isFailure)
|
|
binding.progressHorizontal.goneIf(!isSending)
|
|
|
|
|
|
if (pendingTransaction?.isSubmitSuccess() == true) {
|
|
sendViewModel.reset()
|
|
}
|
|
} catch(t: Throwable) {
|
|
val message = "ERROR: error while handling pending transaction update! $t"
|
|
twig(message)
|
|
Crashlytics.log(message)
|
|
Crashlytics.logException(t)
|
|
}
|
|
}
|
|
|
|
private fun onExit() {
|
|
mainActivity?.navController?.popBackStack(R.id.nav_home, false)
|
|
}
|
|
|
|
private fun onRetry() {
|
|
mainActivity?.navController?.popBackStack(R.id.nav_send_address, false)
|
|
}
|
|
|
|
}
|