add biometrics to confirm digalogbox
Auto Tag on Version Change / check-version (push) Successful in 2s

This commit is contained in:
2026-05-17 21:39:42 +05:00
parent 6197152f6e
commit 04af4e1bbd
8 changed files with 140 additions and 38 deletions
@@ -211,6 +211,7 @@ class HomeActivity : AppCompatActivity() {
R.id.nav_settings -> show(SettingsFragment())
else -> Toast.makeText(this, R.string.work_in_progress, Toast.LENGTH_SHORT).show()
}
binding.navigationView.setCheckedItem(itemId)
val bottomNavIds = setOf(R.id.nav_dashboard, R.id.nav_accounts, R.id.nav_contacts, R.id.nav_transfer, R.id.nav_more)
if (binding.bottomNavigation.visibility == View.VISIBLE && itemId in bottomNavIds) {
suppressBottomNavCallback = true
@@ -17,6 +17,7 @@ class MoreFragment : Fragment() {
private data class NavItem(val id: Int, @DrawableRes val icon: Int, @StringRes val title: Int)
private val items = listOf(
NavItem(R.id.nav_pay_mv_qr, R.drawable.ic_qr_scan, R.string.pay_mv_qr),
NavItem(R.id.nav_activities, R.drawable.ic_nav_activities, R.string.nav_activities),
NavItem(R.id.nav_transfer_history, R.drawable.ic_nav_transfer_history, R.string.nav_transfer_history),
NavItem(R.id.nav_finances, R.drawable.ic_nav_finances, R.string.nav_finances),
@@ -36,9 +36,23 @@ class SettingsSecurityFragment : Fragment() {
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS
if (canUseBiometrics) {
binding.rowBiometrics.visibility = View.VISIBLE
binding.switchBiometrics.isChecked = prefs.getBoolean("biometrics_enabled", false)
val unlockEnabled = prefs.getBoolean("biometrics_enabled", false)
binding.switchBiometrics.isChecked = unlockEnabled
binding.switchBiometricsTransfer.isChecked = prefs.getBoolean("biometrics_transfer_confirm", false)
binding.switchBiometricsTransfer.isEnabled = unlockEnabled
binding.switchBiometrics.setOnCheckedChangeListener { _, isChecked ->
prefs.edit().putBoolean("biometrics_enabled", isChecked).apply()
binding.switchBiometricsTransfer.isEnabled = isChecked
if (!isChecked) {
binding.switchBiometricsTransfer.isChecked = false
prefs.edit().putBoolean("biometrics_transfer_confirm", false).apply()
}
}
binding.switchBiometricsTransfer.setOnCheckedChangeListener { _, isChecked ->
prefs.edit().putBoolean("biometrics_transfer_confirm", isChecked).apply()
}
}
@@ -19,6 +19,9 @@ import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
@@ -562,29 +565,31 @@ class TransferFragment : Fragment() {
val mainMsg = "Send $currency $amountStr to $destDisplay?\n\nFrom: ${src.accountBriefName} · ${src.accountNumber}"
val dialogBuilder = AlertDialog.Builder(requireContext())
.setTitle(R.string.transfer)
.setPositiveButton(R.string.transfer_confirm) { _, _ ->
binding.btnTransfer.isEnabled = false
viewLifecycleOwner.lifecycleScope.launch {
val (ok, msg, receipt) = withContext(Dispatchers.IO) {
if (!isSrcBml) {
doMibTransfer(src, resolvedAccountNumber, resolvedRecipientName, destDisplay, amountStr, remarks, bankNameCapture)
} else {
doBmlTransfer(src, resolvedAccountNumber, destDisplay, amount, amountStr, remarks, isSrcCard, isDestMib, currency, allAccounts, allContacts)
}
}
binding.btnTransfer.isEnabled = true
if (ok && receipt != null) {
clearForm()
val activity = requireActivity() as HomeActivity
activity.refreshBalances(src)
activity.showWithBackStack(TransferReceiptFragment.newInstance(receipt, capturedToAvatar))
} else if (!ok) {
Toast.makeText(requireContext(), msg, Toast.LENGTH_LONG).show()
val doTransfer: () -> Unit = {
binding.btnTransfer.isEnabled = false
viewLifecycleOwner.lifecycleScope.launch {
val (ok, msg, receipt) = withContext(Dispatchers.IO) {
if (!isSrcBml) {
doMibTransfer(src, resolvedAccountNumber, resolvedRecipientName, destDisplay, amountStr, remarks, bankNameCapture)
} else {
doBmlTransfer(src, resolvedAccountNumber, destDisplay, amount, amountStr, remarks, isSrcCard, isDestMib, currency, allAccounts, allContacts)
}
}
binding.btnTransfer.isEnabled = true
if (ok && receipt != null) {
clearForm()
val activity = requireActivity() as HomeActivity
activity.refreshBalances(src)
activity.showWithBackStack(TransferReceiptFragment.newInstance(receipt, capturedToAvatar))
} else if (!ok) {
Toast.makeText(requireContext(), msg, Toast.LENGTH_LONG).show()
}
}
}
val dialogBuilder = AlertDialog.Builder(requireContext())
.setTitle(R.string.transfer)
.setPositiveButton(R.string.transfer_confirm) { _, _ -> doTransfer() }
.setNegativeButton(android.R.string.cancel, null)
if (isUsdToMvr) {
@@ -606,7 +611,39 @@ class TransferFragment : Fragment() {
} else {
dialogBuilder.setMessage(mainMsg)
}
dialogBuilder.show()
val dialog = dialogBuilder.show()
val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE)
val biometricTransferConfirm = prefs.getBoolean("biometrics_transfer_confirm", false)
val canAuth = BiometricManager.from(requireContext())
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS
if (biometricTransferConfirm && canAuth) {
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val prompt = BiometricPrompt(this, ContextCompat.getMainExecutor(requireContext()),
object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
dialog.dismiss()
doTransfer()
}
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
if (errorCode != BiometricPrompt.ERROR_CANCELED &&
errorCode != BiometricPrompt.ERROR_USER_CANCELED &&
errorCode != BiometricPrompt.ERROR_NEGATIVE_BUTTON) {
Toast.makeText(requireContext(), errString, Toast.LENGTH_SHORT).show()
}
}
override fun onAuthenticationFailed() { /* keep dialog open */ }
})
prompt.authenticate(
BiometricPrompt.PromptInfo.Builder()
.setTitle(getString(R.string.biometric_transfer_title))
.setSubtitle("$currency $amountStr$destDisplay")
.setNegativeButtonText(getString(android.R.string.cancel))
.build()
)
}
}
}
private fun doMibTransfer(