forked from shihaam/thijooree
improve QR scan flow part:1 unified
This commit is contained in:
@@ -4,13 +4,13 @@ import android.app.Activity
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
@@ -25,8 +25,8 @@ import sh.sar.basedbank.api.models.BankAccount
|
|||||||
import sh.sar.basedbank.api.mib.MibCard
|
import sh.sar.basedbank.api.mib.MibCard
|
||||||
import sh.sar.basedbank.api.mib.MibFinanceDeal
|
import sh.sar.basedbank.api.mib.MibFinanceDeal
|
||||||
import sh.sar.basedbank.util.bmlapi.BmlCardParser
|
import sh.sar.basedbank.util.bmlapi.BmlCardParser
|
||||||
import sh.sar.basedbank.util.PaymvQrParser
|
|
||||||
import sh.sar.basedbank.util.CredentialStore
|
import sh.sar.basedbank.util.CredentialStore
|
||||||
|
import sh.sar.basedbank.util.PaymvQrParser
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import sh.sar.basedbank.databinding.FragmentDashboardBinding
|
import sh.sar.basedbank.databinding.FragmentDashboardBinding
|
||||||
import sh.sar.basedbank.databinding.ItemForeignLimitBinding
|
import sh.sar.basedbank.databinding.ItemForeignLimitBinding
|
||||||
@@ -36,21 +36,35 @@ class DashboardFragment : Fragment() {
|
|||||||
private var _binding: FragmentDashboardBinding? = null
|
private var _binding: FragmentDashboardBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
private val viewModel: HomeViewModel by activityViewModels()
|
private val viewModel: HomeViewModel by activityViewModels()
|
||||||
|
private var pendingQrCardNumber: String? = null
|
||||||
private var pendingQrAccountNumber: String? = null
|
|
||||||
|
|
||||||
private val qrLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
private val qrLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||||
if (result.resultCode != Activity.RESULT_OK) return@registerForActivityResult
|
if (result.resultCode != Activity.RESULT_OK) return@registerForActivityResult
|
||||||
val raw = result.data?.getStringExtra(QrScannerActivity.EXTRA_QR_CONTENT) ?: return@registerForActivityResult
|
val raw = result.data?.getStringExtra(QrScannerActivity.EXTRA_QR_CONTENT) ?: return@registerForActivityResult
|
||||||
|
val cardNumber = pendingQrCardNumber.also { pendingQrCardNumber = null }
|
||||||
val bmlUrl = PaymvQrParser.extractBmlGatewayUrl(raw)
|
val bmlUrl = PaymvQrParser.extractBmlGatewayUrl(raw)
|
||||||
if (raw.startsWith("https://ebanking.bankofmaldives.com.mv/qrpay/") || bmlUrl != null) {
|
if (raw.startsWith("https://ebanking.bankofmaldives.com.mv/qrpay/") || bmlUrl != null) {
|
||||||
(requireActivity() as HomeActivity).navigateTo(
|
(requireActivity() as HomeActivity).navigateTo(
|
||||||
R.id.nav_transfer, TransferFragment.newInstanceFromBmlQr(bmlUrl ?: raw, pendingQrAccountNumber)
|
R.id.nav_transfer, TransferFragment.newInstanceFromBmlQr(bmlUrl ?: raw, cardNumber)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(requireContext(), R.string.transfer_qr_invalid, Toast.LENGTH_SHORT).show()
|
val qr = PaymvQrParser.parse(raw)
|
||||||
|
if (qr?.accountNumber != null) {
|
||||||
|
Toast.makeText(requireContext(), R.string.card_qr_paymv_unsupported, Toast.LENGTH_SHORT).show()
|
||||||
|
val defaultFrom = CredentialStore(requireContext()).getDefaultAccountNumber()
|
||||||
|
(requireActivity() as HomeActivity).navigateTo(
|
||||||
|
R.id.nav_transfer, TransferFragment.newInstanceFromQr(
|
||||||
|
accountNumber = qr.accountNumber,
|
||||||
|
displayName = qr.merchantName ?: qr.accountNumber,
|
||||||
|
amount = qr.amount,
|
||||||
|
remarks = qr.purpose,
|
||||||
|
fromAccountNumber = defaultFrom
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Toast.makeText(requireContext(), R.string.transfer_qr_invalid, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pendingQrAccountNumber = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
@@ -402,7 +416,7 @@ class DashboardFragment : Fragment() {
|
|||||||
if (isMib) {
|
if (isMib) {
|
||||||
Toast.makeText(requireContext(), R.string.mib_qr_nfc_not_supported, Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), R.string.mib_qr_nfc_not_supported, Toast.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
pendingQrAccountNumber = (item as CardItem.Bml).account.accountNumber
|
pendingQrCardNumber = (item as CardItem.Bml).account.accountNumber
|
||||||
qrLauncher.launch(Intent(requireContext(), QrScannerActivity::class.java))
|
qrLauncher.launch(Intent(requireContext(), QrScannerActivity::class.java))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package sh.sar.basedbank.ui.home
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.GradientDrawable
|
import android.graphics.drawable.GradientDrawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@@ -13,7 +14,6 @@ import android.widget.ImageView
|
|||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import android.view.animation.AccelerateInterpolator
|
import android.view.animation.AccelerateInterpolator
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
@@ -60,8 +60,37 @@ class CardsFragment : Fragment() {
|
|||||||
private var cards: List<CardItem> = emptyList()
|
private var cards: List<CardItem> = emptyList()
|
||||||
private var currentCardPosition: Int = 0
|
private var currentCardPosition: Int = 0
|
||||||
private var cardWidth: Int = 0
|
private var cardWidth: Int = 0
|
||||||
private var pendingQrAccountNumber: String? = null
|
private var pendingQrCardNumber: String? = null
|
||||||
private var isManageMode: Boolean = false
|
private var isManageMode: Boolean = false
|
||||||
|
|
||||||
|
private val qrLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||||
|
if (result.resultCode != Activity.RESULT_OK) return@registerForActivityResult
|
||||||
|
val raw = result.data?.getStringExtra(QrScannerActivity.EXTRA_QR_CONTENT) ?: return@registerForActivityResult
|
||||||
|
val cardNumber = pendingQrCardNumber.also { pendingQrCardNumber = null }
|
||||||
|
val bmlUrl = PaymvQrParser.extractBmlGatewayUrl(raw)
|
||||||
|
if (raw.startsWith("https://ebanking.bankofmaldives.com.mv/qrpay/") || bmlUrl != null) {
|
||||||
|
(requireActivity() as HomeActivity).navigateTo(
|
||||||
|
R.id.nav_transfer, TransferFragment.newInstanceFromBmlQr(bmlUrl ?: raw, cardNumber)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
val qr = PaymvQrParser.parse(raw)
|
||||||
|
if (qr?.accountNumber != null) {
|
||||||
|
Toast.makeText(requireContext(), R.string.card_qr_paymv_unsupported, Toast.LENGTH_SHORT).show()
|
||||||
|
val defaultFrom = store.getDefaultAccountNumber()
|
||||||
|
(requireActivity() as HomeActivity).navigateTo(
|
||||||
|
R.id.nav_transfer, TransferFragment.newInstanceFromQr(
|
||||||
|
accountNumber = qr.accountNumber,
|
||||||
|
displayName = qr.merchantName ?: qr.accountNumber,
|
||||||
|
amount = qr.amount,
|
||||||
|
remarks = qr.purpose,
|
||||||
|
fromAccountNumber = defaultFrom
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Toast.makeText(requireContext(), R.string.transfer_qr_invalid, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
private var isTapMode: Boolean = false
|
private var isTapMode: Boolean = false
|
||||||
private var tapAnimView: NfcTapAnimationView? = null
|
private var tapAnimView: NfcTapAnimationView? = null
|
||||||
private var autoTapModeTriggered = false
|
private var autoTapModeTriggered = false
|
||||||
@@ -78,45 +107,6 @@ class CardsFragment : Fragment() {
|
|||||||
private lateinit var stackAdapter: CardStackAdapter
|
private lateinit var stackAdapter: CardStackAdapter
|
||||||
private val store by lazy { CredentialStore(requireContext()) }
|
private val store by lazy { CredentialStore(requireContext()) }
|
||||||
|
|
||||||
private val qrLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
|
||||||
if (result.resultCode != Activity.RESULT_OK) return@registerForActivityResult
|
|
||||||
val raw = result.data?.getStringExtra(QrScannerActivity.EXTRA_QR_CONTENT) ?: return@registerForActivityResult
|
|
||||||
val bmlUrl = PaymvQrParser.extractBmlGatewayUrl(raw)
|
|
||||||
if (raw.startsWith("https://ebanking.bankofmaldives.com.mv/qrpay/") || bmlUrl != null) {
|
|
||||||
(requireActivity() as HomeActivity).navigateTo(
|
|
||||||
R.id.nav_transfer, TransferFragment.newInstanceFromBmlQr(bmlUrl ?: raw, pendingQrAccountNumber)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
val qr = PaymvQrParser.parse(raw)
|
|
||||||
if (qr?.accountNumber != null) {
|
|
||||||
// PayMV QR — cards are not supported for this payment type.
|
|
||||||
// Navigate to transfer with the recipient pre-filled; use default account if configured.
|
|
||||||
Toast.makeText(requireContext(), R.string.card_qr_paymv_unsupported, Toast.LENGTH_SHORT).show()
|
|
||||||
val defaultFromNumber = store.getDefaultAccountNumber()
|
|
||||||
val fragment = if (defaultFromNumber != null) {
|
|
||||||
TransferFragment.newInstanceFromQrWithFrom(
|
|
||||||
accountNumber = qr.accountNumber,
|
|
||||||
displayName = qr.merchantName ?: qr.accountNumber,
|
|
||||||
amount = qr.amount,
|
|
||||||
remarks = qr.purpose,
|
|
||||||
fromAccountNumber = defaultFromNumber
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
TransferFragment.newInstanceFromQr(
|
|
||||||
accountNumber = qr.accountNumber,
|
|
||||||
displayName = qr.merchantName ?: qr.accountNumber,
|
|
||||||
amount = qr.amount,
|
|
||||||
remarks = qr.purpose
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(requireActivity() as HomeActivity).navigateTo(R.id.nav_transfer, fragment)
|
|
||||||
} else {
|
|
||||||
Toast.makeText(requireContext(), R.string.transfer_qr_invalid, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pendingQrAccountNumber = null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
_binding = FragmentCardsBinding.inflate(inflater, container, false)
|
_binding = FragmentCardsBinding.inflate(inflater, container, false)
|
||||||
return binding.root
|
return binding.root
|
||||||
@@ -228,7 +218,7 @@ ViewCompat.setOnApplyWindowInsetsListener(binding.contentLayout) { v, insets ->
|
|||||||
if (item is CardItem.Mib) {
|
if (item is CardItem.Mib) {
|
||||||
Toast.makeText(requireContext(), R.string.mib_qr_nfc_not_supported, Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), R.string.mib_qr_nfc_not_supported, Toast.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
pendingQrAccountNumber = (item as CardItem.Bml).account.accountNumber
|
pendingQrCardNumber = (item as CardItem.Bml).account.accountNumber
|
||||||
qrLauncher.launch(Intent(requireContext(), QrScannerActivity::class.java))
|
qrLauncher.launch(Intent(requireContext(), QrScannerActivity::class.java))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,6 +139,28 @@ class TransferFragment : Fragment() {
|
|||||||
Toast.makeText(requireContext(), R.string.transfer_qr_invalid, Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireContext(), R.string.transfer_qr_invalid, Toast.LENGTH_SHORT).show()
|
||||||
return@registerForActivityResult
|
return@registerForActivityResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cards can't pay PayMV QR — fall back to default account or clear selection
|
||||||
|
val isCard = selectedAccount?.let {
|
||||||
|
it.profileType == "BML_PREPAID" || it.profileType == "BML_CREDIT" || it.profileType == "BML_DEBIT"
|
||||||
|
} ?: false
|
||||||
|
if (isCard) {
|
||||||
|
Toast.makeText(requireContext(), R.string.card_qr_paymv_unsupported, Toast.LENGTH_SHORT).show()
|
||||||
|
val defaultNum = CredentialStore(requireContext()).getDefaultAccountNumber()
|
||||||
|
val defaultAcc = defaultNum?.let { num -> viewModel.accounts.value?.firstOrNull { it.accountNumber == num } }
|
||||||
|
selectedAccount = defaultAcc
|
||||||
|
binding.tilAmount.prefixText = null
|
||||||
|
if (defaultAcc != null) {
|
||||||
|
updateAmountPrefix(defaultAcc)
|
||||||
|
showFromCard(defaultAcc)
|
||||||
|
} else {
|
||||||
|
binding.cardFromInfo.visibility = View.GONE
|
||||||
|
binding.tilFrom.visibility = View.VISIBLE
|
||||||
|
binding.actvFrom.setText("", false)
|
||||||
|
}
|
||||||
|
updateTransferButton()
|
||||||
|
}
|
||||||
|
|
||||||
if (qr.amount != null) binding.etAmount.setText(qr.amount)
|
if (qr.amount != null) binding.etAmount.setText(qr.amount)
|
||||||
if (qr.purpose != null) binding.etRemarks.setText(qr.purpose)
|
if (qr.purpose != null) binding.etRemarks.setText(qr.purpose)
|
||||||
prefillToFromContact(qr.accountNumber, "")
|
prefillToFromContact(qr.accountNumber, "")
|
||||||
@@ -188,34 +210,18 @@ class TransferFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun newInstanceFromQr(
|
fun newInstanceFromQr(
|
||||||
accountNumber: String,
|
|
||||||
displayName: String,
|
|
||||||
amount: String?,
|
|
||||||
remarks: String?
|
|
||||||
) = TransferFragment().apply {
|
|
||||||
arguments = Bundle().apply {
|
|
||||||
putString(ARG_ACCOUNT, accountNumber)
|
|
||||||
putString(ARG_NAME, displayName)
|
|
||||||
putString(ARG_SUBTITLE, accountNumber)
|
|
||||||
putString(ARG_COLOR, "#607D8B")
|
|
||||||
if (amount != null) putString(ARG_AMOUNT_PREFILL, amount)
|
|
||||||
if (remarks != null) putString(ARG_REMARKS_PREFILL, remarks)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun newInstanceFromQrWithFrom(
|
|
||||||
accountNumber: String,
|
accountNumber: String,
|
||||||
displayName: String,
|
displayName: String,
|
||||||
amount: String?,
|
amount: String?,
|
||||||
remarks: String?,
|
remarks: String?,
|
||||||
fromAccountNumber: String
|
fromAccountNumber: String? = null
|
||||||
) = TransferFragment().apply {
|
) = TransferFragment().apply {
|
||||||
arguments = Bundle().apply {
|
arguments = Bundle().apply {
|
||||||
putString(ARG_ACCOUNT, accountNumber)
|
putString(ARG_ACCOUNT, accountNumber)
|
||||||
putString(ARG_NAME, displayName)
|
putString(ARG_NAME, displayName)
|
||||||
putString(ARG_SUBTITLE, accountNumber)
|
putString(ARG_SUBTITLE, accountNumber)
|
||||||
putString(ARG_COLOR, "#607D8B")
|
putString(ARG_COLOR, "#607D8B")
|
||||||
putString(ARG_FROM_ACCOUNT, fromAccountNumber)
|
if (fromAccountNumber != null) putString(ARG_FROM_ACCOUNT, fromAccountNumber)
|
||||||
if (amount != null) putString(ARG_AMOUNT_PREFILL, amount)
|
if (amount != null) putString(ARG_AMOUNT_PREFILL, amount)
|
||||||
if (remarks != null) putString(ARG_REMARKS_PREFILL, remarks)
|
if (remarks != null) putString(ARG_REMARKS_PREFILL, remarks)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user