Skip to content

Instantly share code, notes, and snippets.

@zamahaka
Created June 4, 2019 14:16
Show Gist options
  • Save zamahaka/0056b9d417751881367c5297e1ee4dcb to your computer and use it in GitHub Desktop.
Save zamahaka/0056b9d417751881367c5297e1ee4dcb to your computer and use it in GitHub Desktop.
class InvoiceActivity : BaseActivity(), HasBottomBar, HasToolbar {
private val paymentId: Long by longExtra(PAYMENT_ID)
private val viewModel by viewModel<InvoiceViewModel> {
parametersOf(paymentId)
}
private val paymentViewBinder by lazy { PaymentViewBinder(layoutInvoice) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent(R.layout.activity_invoice)
screenTitle = getString(R.string.invoice)
viewModel.errors.observeAsOkAlert()
viewModel.paymentSummaryItem.observe {
invalidateOptionsMenu()
setupTransactionData(it)
}
viewModel.declineProgress.observeProgressButton(
button = btnDecline,
progress = progressDecline,
textProvider = {
getString(
if (viewModel.paymentSummaryItem.value?.transaction?.isMyInvoice() == true)
R.string.decline else R.string.cancel
)
}
)
viewModel.approveProgress.observeProgressButton(
text = R.string.approve,
button = btnApprove,
progress = progressApprove
)
viewModel.navigationEvent.observe(this::handleNavigation)
btnPrint.onClick(this::printInvoice)
btnApprove.onClick(viewModel::approveInvoice)
btnDecline.onClick(viewModel::declineInvoice)
txtViewInExplorer.onClick(viewModel::viewInExplorer)
clickSenderAddress.onClick {
val senderAddressLabel = getString(R.string.sender_address)
val senderAddress: String = viewModel.paymentSummaryItem.value
?.transaction?.senderAddress ?: return@onClick
copyToClipBoard(label = senderAddressLabel, value = senderAddress)
showCopiedToast(senderAddressLabel)
}
clickReceiverAddress.onClick {
val receiverAddressLabel = getString(R.string.receiver_address)
val receiverAddress: String = viewModel.paymentSummaryItem.value
?.transaction?.receiverAddress ?: return@onClick
copyToClipBoard(label = receiverAddressLabel, value = receiverAddress)
showCopiedToast(receiverAddressLabel)
}
clickTransactionHash.onClick {
val transactionHashLabel = getString(R.string.transaction_hash)
val transactionHash: String = viewModel.paymentSummaryItem.value
?.transaction?.transactionHash ?: return@onClick
copyToClipBoard(label = transactionHashLabel, value = transactionHash)
showCopiedToast(transactionHashLabel)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) when (requestCode) {
ADD_CONTACT -> viewModel.refreshPayment()
CREATE_ACCESS_CODE_REQUEST -> viewModel.pinCreated()
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.invoice, menu)
return true
}
override fun onPrepareOptionsMenu(menu: Menu?): Boolean = when (
val payment = viewModel.paymentSummaryItem.value
) {
null -> false
else -> {
menu?.findItem(R.id.menu_add_contact)?.isVisible = isAddContactAvailable(payment)
true
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
R.id.menu_add_contact -> {
viewModel.addAsContact()
true
}
R.id.menu_share -> {
sharePayment()
true
}
else -> super.onOptionsItemSelected(item)
}
// NOTE: false for now as api doesn't support contacts for now
private fun isAddContactAvailable(@Suppress("UNUSED_PARAMETER") payment: TransactionMeta) = false
private fun setupTransactionData(meta: TransactionMeta) = paymentViewBinder.bind(meta)
private fun handleNavigation(navigation: InvoiceNavigation) = when (navigation) {
is ShowApproveEvent -> showApproveDialog(
meta = navigation.meta,
isFromUnknown = navigation.isFromUnknown,
isPinRequired = navigation.requirePin
)
is ShowAddContact -> startActivityForResult(
AddEditContactActivity.addIntent(
context = this,
ethAddress = navigation.ehtAddress
), ADD_CONTACT
)
is ShowDeclineEvent -> showDeclinedDialog(
meta = navigation.meta,
requirePin = navigation.requirePin
)
is ShowBlockchainExplorer -> startIntentSafe(
Intent(Intent.ACTION_VIEW, Uri.parse(navigation.url))
)
is ShowCreatePin -> showCreatePinDialog(CREATE_ACCESS_CODE_REQUEST)
Finish -> finish()
}
private fun printInvoice() {
if (!layoutInvoice.isLaidOut) return
val meta = viewModel.paymentSummaryItem.value ?: return
PrintHelper(this)
.apply { scaleMode = PrintHelper.SCALE_MODE_FIT }
.printBitmap(getString(R.string.invoice), createInvoiceBitmap(meta))
}
private fun sharePayment() {
if (!layoutInvoice.isLaidOut) return
val meta = viewModel.paymentSummaryItem.value ?: return
val invoiceFile = File(filesDir, "payment.jpg")
FileOutputStream(invoiceFile).use { outputStream ->
createInvoiceBitmap(meta)
.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
}
FileProvider.getUriForFile(
this, applicationContext.packageName, invoiceFile
)?.let { uri ->
val shareIntent = Intent(Intent.ACTION_SEND).apply {
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
setDataAndType(uri, contentResolver.getType(uri))
putExtra(Intent.EXTRA_STREAM, uri)
}
if (shareIntent.resolveActivity(packageManager) != null) {
startActivity(Intent.createChooser(shareIntent, getString(R.string.share_with)))
} else toast(getString(R.string.cant_find_an_app_to_share_with))
}
}
private fun createInvoiceBitmap(meta: TransactionMeta): Bitmap {
val width = layoutInvoice.width
val height = layoutInvoice.height
return layoutInflater.inflate(
R.layout.layout_invoice_info, layoutInvoice, false
)
.invoiceCard
.also {
PaymentViewBinder(it).apply {
bind(meta)
prepareToShare()
}
}
.apply {
measure(
makeMeasureSpec(width, EXACTLY),
makeMeasureSpec(height, UNSPECIFIED)
)
layout(
0, 0,
measuredWidth, measuredHeight
)
}
.getBitmap()
}
private fun showApproveDialog(
meta: TransactionMeta,
isFromUnknown: Boolean,
isPinRequired: Boolean
) {
val title = getString(
if (isFromUnknown) R.string.approve_request_from_unknown else R.string.you_are_now_approving_request
)
transactionActionDialog(
context = this,
dialogData = TransactionActionDialogData(
isPinCheckEnabled = isPinRequired,
header = getString(R.string.approve_request),
caption = title,
pinLength = BuildConfig.PIN_LENGHT,
transactionMeta = meta,
positiveButtonText = getString(R.string.send)
)
) {
onPositive { message, pin ->
viewModel.approveInvoiceWithMessage(
message = message,
pin = if (isPinRequired) pin else null
)
}
}.show()
}
private fun showDeclinedDialog(meta: TransactionMeta, requirePin: Boolean) {
val positiveButtonText = getString(
if (meta.transaction.isMyRequest()) R.string.cancel else R.string.decline
)
val header = getString(
if (meta.transaction.isMyRequest()) R.string.cancel_request else R.string.decline_request
)
val title = if (meta.transaction.isMyRequest()) null else getString(R.string.title_request_declined)
transactionActionDialog(
context = this,
dialogData = TransactionActionDialogData(
isPinCheckEnabled = requirePin,
header = header,
caption = title,
pinLength = BuildConfig.PIN_LENGHT,
transactionMeta = meta,
positiveButtonText = positiveButtonText,
messageVisible = !meta.transaction.isMyRequest()
)
) {
onPositive { message, pin ->
viewModel.declineInvoiceWithMessage(
message = message,
pin = if (requirePin) pin else null
)
}
}.show()
}
companion object {
private const val ADD_CONTACT = 1
private const val CREATE_ACCESS_CODE_REQUEST = 2
private const val PAYMENT_ID = "payment_id"
fun intent(
context: Context,
paymentId: Long
) = context.intentFor<InvoiceActivity>(PAYMENT_ID to paymentId)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment