Avoid requesting storage permission to share eReceipt.
This commit is contained in:
parent
ac06a3d708
commit
23f4170628
3 changed files with 64 additions and 101 deletions
|
@ -16,7 +16,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.recyclerview.widget.SortedList
|
import androidx.recyclerview.widget.SortedList
|
||||||
import cy.agorise.bitsybitshareswallet.R
|
import cy.agorise.bitsybitshareswallet.R
|
||||||
import cy.agorise.bitsybitshareswallet.database.joins.TransferDetail
|
import cy.agorise.bitsybitshareswallet.database.joins.TransferDetail
|
||||||
import cy.agorise.bitsybitshareswallet.fragments.TransactionsFragmentDirections
|
import cy.agorise.bitsybitshareswallet.ui.transactions.TransactionsFragmentDirections
|
||||||
import java.math.RoundingMode
|
import java.math.RoundingMode
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import java.text.DecimalFormatSymbols
|
import java.text.DecimalFormatSymbols
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package cy.agorise.bitsybitshareswallet.fragments
|
package cy.agorise.bitsybitshareswallet.fragments
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.graphics.drawable.Animatable
|
import android.graphics.drawable.Animatable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.method.LinkMovementMethod
|
import android.text.method.LinkMovementMethod
|
||||||
|
@ -20,7 +18,6 @@ import cy.agorise.bitsybitshareswallet.database.joins.TransferDetail
|
||||||
import cy.agorise.bitsybitshareswallet.databinding.FragmentEReceiptBinding
|
import cy.agorise.bitsybitshareswallet.databinding.FragmentEReceiptBinding
|
||||||
import cy.agorise.bitsybitshareswallet.utils.Constants
|
import cy.agorise.bitsybitshareswallet.utils.Constants
|
||||||
import cy.agorise.bitsybitshareswallet.utils.Helper
|
import cy.agorise.bitsybitshareswallet.utils.Helper
|
||||||
import cy.agorise.bitsybitshareswallet.utils.toast
|
|
||||||
import cy.agorise.bitsybitshareswallet.viewmodels.EReceiptViewModel
|
import cy.agorise.bitsybitshareswallet.viewmodels.EReceiptViewModel
|
||||||
import java.math.RoundingMode
|
import java.math.RoundingMode
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
|
@ -28,15 +25,10 @@ import java.text.DecimalFormatSymbols
|
||||||
import java.text.NumberFormat
|
import java.text.NumberFormat
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
class EReceiptFragment : Fragment() {
|
class EReceiptFragment : Fragment() {
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "EReceiptFragment"
|
|
||||||
|
|
||||||
private const val REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION = 100
|
|
||||||
}
|
|
||||||
|
|
||||||
private val args: EReceiptFragmentArgs by navArgs()
|
private val args: EReceiptFragmentArgs by navArgs()
|
||||||
|
|
||||||
private val viewModel: EReceiptViewModel by viewModels()
|
private val viewModel: EReceiptViewModel by viewModels()
|
||||||
|
@ -75,9 +67,9 @@ class EReceiptFragment : Fragment() {
|
||||||
|
|
||||||
val transferId = args.transferId
|
val transferId = args.transferId
|
||||||
|
|
||||||
viewModel.get(userId, transferId).observe(viewLifecycleOwner, { transferDetail ->
|
viewModel.get(userId, transferId).observe(viewLifecycleOwner) { transferDetail ->
|
||||||
bindTransferDetail(transferDetail)
|
bindTransferDetail(transferDetail)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindTransferDetail(transferDetail: TransferDetail) {
|
private fun bindTransferDetail(transferDetail: TransferDetail) {
|
||||||
|
@ -95,7 +87,7 @@ class EReceiptFragment : Fragment() {
|
||||||
df.decimalFormatSymbols = DecimalFormatSymbols(Locale.getDefault())
|
df.decimalFormatSymbols = DecimalFormatSymbols(Locale.getDefault())
|
||||||
|
|
||||||
val amount = transferDetail.assetAmount.toDouble() /
|
val amount = transferDetail.assetAmount.toDouble() /
|
||||||
Math.pow(10.toDouble(), transferDetail.assetPrecision.toDouble())
|
10.toDouble().pow(transferDetail.assetPrecision.toDouble())
|
||||||
val assetAmount = "${df.format(amount)} ${transferDetail.getUIAssetSymbol()}"
|
val assetAmount = "${df.format(amount)} ${transferDetail.getUIAssetSymbol()}"
|
||||||
binding.tvAmount.text = assetAmount
|
binding.tvAmount.text = assetAmount
|
||||||
|
|
||||||
|
@ -104,7 +96,7 @@ class EReceiptFragment : Fragment() {
|
||||||
val numberFormat = NumberFormat.getNumberInstance()
|
val numberFormat = NumberFormat.getNumberInstance()
|
||||||
val currency = Currency.getInstance(transferDetail.fiatSymbol)
|
val currency = Currency.getInstance(transferDetail.fiatSymbol)
|
||||||
val fiatEquivalent = transferDetail.fiatAmount.toDouble() /
|
val fiatEquivalent = transferDetail.fiatAmount.toDouble() /
|
||||||
Math.pow(10.0, currency.defaultFractionDigits.toDouble())
|
10.0.pow(currency.defaultFractionDigits.toDouble())
|
||||||
|
|
||||||
val equivalentValue = "${numberFormat.format(fiatEquivalent)} ${currency.currencyCode}"
|
val equivalentValue = "${numberFormat.format(fiatEquivalent)} ${currency.currencyCode}"
|
||||||
binding.tvEquivalentValue.text = equivalentValue
|
binding.tvEquivalentValue.text = equivalentValue
|
||||||
|
@ -151,47 +143,13 @@ class EReceiptFragment : Fragment() {
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
if (item.itemId == R.id.menu_share) {
|
if (item.itemId == R.id.menu_share) {
|
||||||
verifyStoragePermission()
|
shareEReceiptScreenshot()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Verifies if the storage permission is already granted, if that is the case then it takes the screenshot and
|
|
||||||
* shares it but if it is not then it asks the user for that permission */
|
|
||||||
private fun verifyStoragePermission() {
|
|
||||||
if (ContextCompat
|
|
||||||
.checkSelfPermission(requireActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
|
||||||
!= PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
// Permission is not already granted
|
|
||||||
requestPermissions(
|
|
||||||
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
|
|
||||||
REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// Permission is already granted
|
|
||||||
shareEReceiptScreenshot()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(
|
|
||||||
requestCode: Int,
|
|
||||||
permissions: Array<out String>,
|
|
||||||
grantResults: IntArray
|
|
||||||
) {
|
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
|
||||||
|
|
||||||
if (requestCode == REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION) {
|
|
||||||
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
|
|
||||||
shareEReceiptScreenshot()
|
|
||||||
} else {
|
|
||||||
context?.toast(getString(R.string.msg__storage_permission_necessary_share))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Takes a screenshot as a bitmap (hiding the tx hyperlink), saves it into a temporal cache image and then
|
/** Takes a screenshot as a bitmap (hiding the tx hyperlink), saves it into a temporal cache image and then
|
||||||
* sends an intent so the user can select the desired method to share the image. */
|
* sends an intent so the user can select the desired method to share the image. */
|
||||||
private fun shareEReceiptScreenshot() {
|
private fun shareEReceiptScreenshot() {
|
||||||
|
@ -214,4 +172,8 @@ class EReceiptFragment : Fragment() {
|
||||||
shareIntent.type = "*/*"
|
shareIntent.type = "*/*"
|
||||||
startActivity(Intent.createChooser(shareIntent, getString(R.string.text__share_with)))
|
startActivity(Intent.createChooser(shareIntent, getString(R.string.text__share_with)))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "EReceiptFragment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -81,8 +81,6 @@ class TransactionsViewModel(application: Application) : AndroidViewModel(applica
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getFilteredTransactionsOnce() = filteredTransactions.value
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters the given list of [TransferDetail] given the [FilterOptions] and returns a filtered list
|
* Filters the given list of [TransferDetail] given the [FilterOptions] and returns a filtered list
|
||||||
* of [TransferDetail], doing all the work in a background thread using kotlin coroutines
|
* of [TransferDetail], doing all the work in a background thread using kotlin coroutines
|
||||||
|
@ -90,58 +88,56 @@ class TransactionsViewModel(application: Application) : AndroidViewModel(applica
|
||||||
private suspend fun filter(
|
private suspend fun filter(
|
||||||
transactions: List<TransferDetail>,
|
transactions: List<TransferDetail>,
|
||||||
filterOptions: FilterOptions
|
filterOptions: FilterOptions
|
||||||
): List<TransferDetail> {
|
): List<TransferDetail> = withContext(Dispatchers.Default) {
|
||||||
return withContext(Dispatchers.Default) {
|
|
||||||
|
|
||||||
// Create a list to store the filtered transactions
|
// Create a list to store the filtered transactions
|
||||||
val filteredTransactions = ArrayList<TransferDetail>()
|
val filteredTransactions = ArrayList<TransferDetail>()
|
||||||
|
|
||||||
// Make sure the filter dates use the same format as the transactions' dates
|
// Make sure the filter dates use the same format as the transactions' dates
|
||||||
val startDate = filterOptions.startDate / 1000
|
val startDate = filterOptions.startDate / 1000
|
||||||
val endDate = filterOptions.endDate / 1000
|
val endDate = filterOptions.endDate / 1000
|
||||||
|
|
||||||
for (transaction in transactions) {
|
for (transaction in transactions) {
|
||||||
// Filter by transfer direction
|
// Filter by transfer direction
|
||||||
if (transaction.direction) { // Transfer sent
|
if (transaction.direction) { // Transfer sent
|
||||||
if (filterOptions.transactionsDirection == 1)
|
if (filterOptions.transactionsDirection == 1)
|
||||||
// Looking for received transfers only
|
// Looking for received transfers only
|
||||||
continue
|
|
||||||
} else { // Transfer received
|
|
||||||
if (filterOptions.transactionsDirection == 2)
|
|
||||||
// Looking for sent transactions only
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter by date range
|
|
||||||
if (!filterOptions.dateRangeAll && (transaction.date < startDate ||
|
|
||||||
transaction.date > endDate)
|
|
||||||
)
|
|
||||||
continue
|
continue
|
||||||
|
} else { // Transfer received
|
||||||
// Filter by asset
|
if (filterOptions.transactionsDirection == 2)
|
||||||
if (!filterOptions.assetAll && transaction.assetSymbol != filterOptions.asset)
|
// Looking for sent transactions only
|
||||||
continue
|
continue
|
||||||
|
|
||||||
// Filter by equivalent value
|
|
||||||
if (!filterOptions.equivalentValueAll && ((transaction.fiatAmount
|
|
||||||
?: -1) < filterOptions.fromEquivalentValue
|
|
||||||
|| (transaction.fiatAmount ?: -1) > filterOptions.toEquivalentValue)
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
|
|
||||||
// Filter transactions sent to agorise
|
|
||||||
if (filterOptions.agoriseFees && transaction.to.equals("agorise"))
|
|
||||||
continue
|
|
||||||
|
|
||||||
// Filter by search query
|
|
||||||
val text = "${transaction.from ?: ""} ${transaction.to ?: ""} ${transaction.memo}"
|
|
||||||
if (text.contains(filterOptions.query, ignoreCase = true)) {
|
|
||||||
filteredTransactions.add(transaction)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filteredTransactions
|
// Filter by date range
|
||||||
|
if (!filterOptions.dateRangeAll && (transaction.date < startDate ||
|
||||||
|
transaction.date > endDate)
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
// Filter by asset
|
||||||
|
if (!filterOptions.assetAll && transaction.assetSymbol != filterOptions.asset)
|
||||||
|
continue
|
||||||
|
|
||||||
|
// Filter by equivalent value
|
||||||
|
if (!filterOptions.equivalentValueAll && ((transaction.fiatAmount
|
||||||
|
?: -1) < filterOptions.fromEquivalentValue
|
||||||
|
|| (transaction.fiatAmount ?: -1) > filterOptions.toEquivalentValue)
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
// Filter transactions sent to agorise
|
||||||
|
if (filterOptions.agoriseFees && transaction.to.equals("agorise"))
|
||||||
|
continue
|
||||||
|
|
||||||
|
// Filter by search query
|
||||||
|
val text = "${transaction.from ?: ""} ${transaction.to ?: ""} ${transaction.memo}"
|
||||||
|
if (text.contains(filterOptions.query, ignoreCase = true)) {
|
||||||
|
filteredTransactions.add(transaction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filteredTransactions
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates the export procedures for PDF and CSV, depending on the user selection. */
|
/** Creates the export procedures for PDF and CSV, depending on the user selection. */
|
||||||
|
@ -152,13 +148,18 @@ class TransactionsViewModel(application: Application) : AndroidViewModel(applica
|
||||||
|
|
||||||
// TODO Use injected context
|
// TODO Use injected context
|
||||||
val folderDocumentFile = DocumentFile.fromTreeUri(getApplication(), folderUri) ?: return
|
val folderDocumentFile = DocumentFile.fromTreeUri(getApplication(), folderUri) ?: return
|
||||||
|
val transactions = filteredTransactions.value ?: return
|
||||||
|
|
||||||
if (exportPdf) {
|
if (exportPdf) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
filteredTransactions.value?.let { transactions ->
|
// TODO Show success/failure message
|
||||||
// TODO Show success/failure message
|
exportTransactionsToPdfUseCase(transactions, folderDocumentFile)
|
||||||
exportTransactionsToPdfUseCase(transactions, folderDocumentFile)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (exportCsv) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
// TODO Export CSV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue