made transfer flow more friendly and vivid UI
Auto Tag on Version Change / check-version (push) Failing after 13m27s
Auto Tag on Version Change / check-version (push) Failing after 13m27s
This commit is contained in:
@@ -857,13 +857,20 @@ class TransferFragment : Fragment() {
|
||||
message: String? = null,
|
||||
customView: android.view.View? = null,
|
||||
biometricSubtitle: String,
|
||||
onConfirmed: () -> Unit
|
||||
onConfirmed: (AlertDialog, android.widget.FrameLayout) -> Unit
|
||||
) {
|
||||
val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as android.view.inputmethod.InputMethodManager
|
||||
imm.hideSoftInputFromWindow(requireView().windowToken, 0)
|
||||
|
||||
val frame = android.widget.FrameLayout(requireContext())
|
||||
if (customView != null) frame.addView(customView)
|
||||
|
||||
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(title)
|
||||
.setPositiveButton(R.string.transfer_confirm) { _, _ -> onConfirmed() }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
if (customView != null) builder.setView(customView) else builder.setMessage(message)
|
||||
.setPositiveButton(R.string.transfer_confirm, null)
|
||||
.setNegativeButton(android.R.string.cancel) { d, _ -> d.dismiss() }
|
||||
.setCancelable(false)
|
||||
if (customView != null) builder.setView(frame) else builder.setMessage(message)
|
||||
val dialog = builder.show()
|
||||
val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE)
|
||||
val biometricTransferConfirm = prefs.getBoolean("biometrics_transfer_confirm", false)
|
||||
@@ -874,8 +881,7 @@ class TransferFragment : Fragment() {
|
||||
val prompt = BiometricPrompt(this, ContextCompat.getMainExecutor(requireContext()),
|
||||
object : BiometricPrompt.AuthenticationCallback() {
|
||||
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
|
||||
dialog.dismiss()
|
||||
onConfirmed()
|
||||
onConfirmed(dialog, frame)
|
||||
}
|
||||
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||
if (errorCode != BiometricPrompt.ERROR_CANCELED &&
|
||||
@@ -894,6 +900,10 @@ class TransferFragment : Fragment() {
|
||||
.build()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
onConfirmed(dialog, frame)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -912,11 +922,27 @@ class TransferFragment : Fragment() {
|
||||
Toast.makeText(requireContext(), R.string.transfer_missing_internal_id, Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
val qrFromTypeLabel = AccountListParser.from(src)?.typeLabel
|
||||
?: BmlDashboardParser.productLabel(src.accountTypeName)
|
||||
val qrFromDetail = listOfNotNull("BML", qrFromTypeLabel.ifBlank { null }).joinToString(" · ")
|
||||
val qrConfirmView = buildTransferConfirmView(
|
||||
amountCurrency = info.currency,
|
||||
amountValue = "%.2f".format(amount),
|
||||
fromName = src.accountBriefName,
|
||||
fromNumber = src.accountNumber,
|
||||
fromDetail = qrFromDetail,
|
||||
toName = info.merchantName,
|
||||
toNumber = "",
|
||||
toDetail = info.merchantAddress.ifBlank { "BML Merchant" }
|
||||
)
|
||||
showConfirmWithBiometric(
|
||||
title = getString(R.string.transfer),
|
||||
message = "Pay ${info.currency} ${"%.2f".format(amount)} to ${info.merchantName}?\n\nFrom: ${src.accountBriefName} · ${src.accountNumber}",
|
||||
customView = qrConfirmView,
|
||||
biometricSubtitle = "${info.currency} ${"%.2f".format(amount)} → ${info.merchantName}",
|
||||
onConfirmed = { executeBmlQrPayment(src, debitAccount, info, amount) }
|
||||
onConfirmed = { dialog, frame ->
|
||||
showProcessingInDialog(dialog, frame)
|
||||
executeBmlQrPayment(src, debitAccount, info, amount, dialog, frame)
|
||||
}
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -971,18 +997,17 @@ class TransferFragment : Fragment() {
|
||||
val isUsdToMvr = currency.equals("USD", ignoreCase = true) && destCurrency.equals("MVR", ignoreCase = true)
|
||||
val isSrcCredit = src.profileType == "BML_CREDIT"
|
||||
|
||||
val mainMsg = "Send $currency $amountStr to $destDisplay?\n\nFrom: ${src.accountBriefName} · ${src.accountNumber}"
|
||||
|
||||
val doTransfer: () -> Unit = {
|
||||
val doTransfer: (AlertDialog, android.widget.FrameLayout) -> Unit = { dialog, frame ->
|
||||
if (isBmlBusiness) {
|
||||
// Business profile: async OTP channel selection flow
|
||||
// Business profile: async OTP channel selection flow — dismiss dialog first
|
||||
dialog.dismiss()
|
||||
startBmlBusinessOtpFlow(
|
||||
src, resolvedAccountNumber, destDisplay, amount, amountStr, remarks,
|
||||
isSrcCard, isDestMib, currency, allAccounts, allContacts, capturedToAvatar
|
||||
)
|
||||
} else {
|
||||
showProcessingInDialog(dialog, frame)
|
||||
binding.btnTransfer.isEnabled = false
|
||||
(activity as? HomeActivity)?.setRefreshing(true)
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
val (ok, msg, receipt) = withContext(Dispatchers.IO) {
|
||||
if (!isSrcBml) {
|
||||
@@ -992,14 +1017,15 @@ class TransferFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
binding.btnTransfer.isEnabled = true
|
||||
(activity as? HomeActivity)?.setRefreshing(false)
|
||||
if (ok && receipt != null) {
|
||||
ReceiptStore.save(requireContext(), receipt)
|
||||
clearForm()
|
||||
val activity = requireActivity() as HomeActivity
|
||||
activity.triggerRefresh()
|
||||
dialog.dismiss()
|
||||
activity.showWithBackStack(TransferReceiptFragment.newInstance(receipt, capturedToAvatar))
|
||||
} else if (!ok) {
|
||||
dialog.dismiss()
|
||||
if (msg == "CONNECTIVITY") {
|
||||
(activity as? HomeActivity)?.showConnectivityBanner(getString(R.string.connectivity_no_internet))
|
||||
} else {
|
||||
@@ -1010,56 +1036,202 @@ class TransferFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
val warningView: android.view.View? = if (isUsdToMvr || isSrcCredit) {
|
||||
val ctx = requireContext()
|
||||
val dp = resources.displayMetrics.density
|
||||
LinearLayout(ctx).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
setPadding((24 * dp).toInt(), (16 * dp).toInt(), (24 * dp).toInt(), 0)
|
||||
addView(TextView(ctx).apply { text = mainMsg })
|
||||
if (isUsdToMvr) addView(TextView(ctx).apply {
|
||||
text = "⚠ You are transferring from a USD account to an MVR account. The currency will be converted at the bank's rate and this cannot be reversed!"
|
||||
setTextColor(Color.RED)
|
||||
textSize = 16f
|
||||
typeface = Typeface.DEFAULT_BOLD
|
||||
setPadding(0, (16 * dp).toInt(), 0, 0)
|
||||
})
|
||||
if (isSrcCredit) addView(TextView(ctx).apply {
|
||||
text = "⚠ Transferring from a credit card is treated as a cash advance. Cash advance fees will be charged on the 10th of the month."
|
||||
setTextColor(Color.RED)
|
||||
textSize = 16f
|
||||
typeface = Typeface.DEFAULT_BOLD
|
||||
setPadding(0, (16 * dp).toInt(), 0, 0)
|
||||
})
|
||||
val fromTypeLabel = AccountListParser.from(src)?.typeLabel
|
||||
?: if (src.bank == "BML") BmlDashboardParser.productLabel(src.accountTypeName)
|
||||
else src.accountTypeName.ifBlank { src.profileType }
|
||||
val fromBankLabel = when (src.bank) {
|
||||
"BML" -> "BML"
|
||||
"FAHIPAY" -> "Fahipay"
|
||||
"MIB" -> "MIB"
|
||||
else -> src.bank
|
||||
}
|
||||
val fromDetail = listOfNotNull(fromBankLabel.ifBlank { null }, fromTypeLabel.ifBlank { null }).joinToString(" · ")
|
||||
|
||||
val toTypeLabel = resolvedToOwnAccount?.let { acc ->
|
||||
AccountListParser.from(acc)?.typeLabel
|
||||
?: if (acc.bank == "BML") BmlDashboardParser.productLabel(acc.accountTypeName)
|
||||
else acc.accountTypeName.ifBlank { acc.profileType }
|
||||
}
|
||||
val toBankLabel = resolvedToOwnAccount?.let { acc ->
|
||||
when (acc.bank) {
|
||||
"BML" -> "BML"
|
||||
"FAHIPAY" -> "Fahipay"
|
||||
"MIB" -> "MIB"
|
||||
else -> acc.bank
|
||||
}
|
||||
} else null
|
||||
} ?: when {
|
||||
bankNameCapture.equals("MALBMVMV", ignoreCase = true) -> "BML"
|
||||
bankNameCapture.equals("MADVMVMV", ignoreCase = true) -> "MIB"
|
||||
bankNameCapture.isNotBlank() -> bankNameCapture
|
||||
isDestMib -> "MIB"
|
||||
else -> when (selectedFahipayService) {
|
||||
"RAASTAS" -> "Ooredoo · Raastas"
|
||||
"OOREDOO_BILL" -> "Ooredoo · Bill Pay"
|
||||
"DHIRAAGU_RELOAD" -> "Dhiraagu · Reload"
|
||||
"DHIRAAGU_BILL" -> "Dhiraagu · Bill Pay"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
val toDetail = listOfNotNull(toBankLabel.ifBlank { null }, toTypeLabel?.ifBlank { null }).joinToString(" · ")
|
||||
|
||||
val warnings = buildList {
|
||||
if (isUsdToMvr) add("⚠ You are transferring from a USD account to an MVR account. The currency will be converted at the bank's rate and this cannot be reversed!")
|
||||
if (isSrcCredit) add("⚠ Transferring from a credit card is treated as a cash advance. Cash advance fees will be charged on the 10th of the month.")
|
||||
}
|
||||
val confirmView = buildTransferConfirmView(
|
||||
amountCurrency = currency,
|
||||
amountValue = "%.2f".format(amount),
|
||||
fromName = src.accountBriefName,
|
||||
fromNumber = src.accountNumber,
|
||||
fromDetail = fromDetail,
|
||||
toName = destDisplay,
|
||||
toNumber = resolvedAccountNumber,
|
||||
toDetail = toDetail,
|
||||
warningTexts = warnings
|
||||
)
|
||||
showConfirmWithBiometric(
|
||||
title = getString(R.string.transfer),
|
||||
message = if (warningView == null) mainMsg else null,
|
||||
customView = warningView,
|
||||
biometricSubtitle = "$currency $amountStr → $destDisplay",
|
||||
onConfirmed = { doTransfer() }
|
||||
customView = confirmView,
|
||||
biometricSubtitle = "$currency ${"%.2f".format(amount)} → $destDisplay",
|
||||
onConfirmed = { dialog, frame -> doTransfer(dialog, frame) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildTransferConfirmView(
|
||||
amountCurrency: String,
|
||||
amountValue: String,
|
||||
fromName: String,
|
||||
fromNumber: String,
|
||||
fromDetail: String,
|
||||
toName: String,
|
||||
toNumber: String,
|
||||
toDetail: String,
|
||||
warningTexts: List<String> = emptyList()
|
||||
): android.view.View {
|
||||
val ctx = requireContext()
|
||||
val dp = resources.displayMetrics.density
|
||||
val colorOnSurface = com.google.android.material.color.MaterialColors.getColor(
|
||||
requireView(), com.google.android.material.R.attr.colorOnSurface, Color.BLACK)
|
||||
val colorMuted = com.google.android.material.color.MaterialColors.getColor(
|
||||
requireView(), com.google.android.material.R.attr.colorOnSurfaceVariant, Color.GRAY)
|
||||
val colorPrimary = com.google.android.material.color.MaterialColors.getColor(
|
||||
requireView(), com.google.android.material.R.attr.colorPrimary, Color.BLUE)
|
||||
val MATCH = LinearLayout.LayoutParams.MATCH_PARENT
|
||||
val WRAP = LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
|
||||
fun lp(w: Int = MATCH, h: Int = WRAP, init: LinearLayout.LayoutParams.() -> Unit = {}) =
|
||||
LinearLayout.LayoutParams(w, h).apply(init)
|
||||
|
||||
fun accountBlock(label: String, name: String, number: String, detail: String) =
|
||||
LinearLayout(ctx).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
layoutParams = lp()
|
||||
addView(TextView(ctx).apply {
|
||||
text = label
|
||||
textSize = 10f
|
||||
isAllCaps = true
|
||||
letterSpacing = 0.12f
|
||||
setTextColor(colorMuted)
|
||||
gravity = Gravity.CENTER
|
||||
})
|
||||
addView(TextView(ctx).apply {
|
||||
text = name
|
||||
textSize = 16f
|
||||
setTypeface(null, Typeface.BOLD)
|
||||
setTextColor(colorOnSurface)
|
||||
gravity = Gravity.CENTER
|
||||
layoutParams = lp { topMargin = (2 * dp).toInt() }
|
||||
})
|
||||
if (number.isNotBlank()) addView(TextView(ctx).apply {
|
||||
text = number
|
||||
textSize = 13f
|
||||
setTextColor(colorMuted)
|
||||
gravity = Gravity.CENTER
|
||||
})
|
||||
if (detail.isNotBlank()) addView(TextView(ctx).apply {
|
||||
text = detail
|
||||
textSize = 12f
|
||||
setTextColor(colorMuted)
|
||||
gravity = Gravity.CENTER
|
||||
alpha = 0.75f
|
||||
})
|
||||
}
|
||||
|
||||
return LinearLayout(ctx).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
setPadding((20 * dp).toInt(), (8 * dp).toInt(), (20 * dp).toInt(), (8 * dp).toInt())
|
||||
|
||||
// Currency + amount on same line, centered, baseline-aligned
|
||||
addView(LinearLayout(ctx).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
layoutParams = lp { bottomMargin = (20 * dp).toInt() }
|
||||
addView(TextView(ctx).apply {
|
||||
text = "$amountCurrency "
|
||||
textSize = 16f
|
||||
setTextColor(colorMuted)
|
||||
layoutParams = LinearLayout.LayoutParams(WRAP, WRAP)
|
||||
})
|
||||
addView(TextView(ctx).apply {
|
||||
text = amountValue
|
||||
textSize = 34f
|
||||
setTypeface(null, Typeface.BOLD)
|
||||
setTextColor(colorPrimary)
|
||||
})
|
||||
})
|
||||
|
||||
addView(accountBlock("From", fromName, fromNumber, fromDetail))
|
||||
|
||||
// Down arrow — centered
|
||||
addView(ImageView(ctx).apply {
|
||||
setImageResource(R.drawable.ic_arrow_right)
|
||||
rotation = 90f
|
||||
setColorFilter(colorMuted)
|
||||
layoutParams = lp(WRAP, WRAP) {
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
width = (24 * dp).toInt()
|
||||
height = (24 * dp).toInt()
|
||||
topMargin = (12 * dp).toInt()
|
||||
bottomMargin = (12 * dp).toInt()
|
||||
}
|
||||
})
|
||||
|
||||
addView(accountBlock("To", toName, toNumber, toDetail))
|
||||
|
||||
for (warning in warningTexts) {
|
||||
addView(TextView(ctx).apply {
|
||||
text = warning
|
||||
setTextColor(Color.RED)
|
||||
textSize = 14f
|
||||
setTypeface(null, Typeface.BOLD)
|
||||
layoutParams = lp { topMargin = (16 * dp).toInt() }
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun executeBmlQrPayment(
|
||||
src: BankAccount,
|
||||
debitAccount: String,
|
||||
info: BmlQrPayInfo,
|
||||
amount: Double
|
||||
amount: Double,
|
||||
dialog: AlertDialog,
|
||||
frame: android.widget.FrameLayout
|
||||
) {
|
||||
val app = requireActivity().application as BasedBankApp
|
||||
val loginId = src.loginTag.removePrefix("bml_")
|
||||
val session = bmlSessionFor(src) ?: run {
|
||||
dialog.dismiss()
|
||||
Toast.makeText(requireContext(), R.string.transfer_session_unavailable, Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
val otp = CredentialStore(requireContext()).loadBmlCredentials(loginId)?.otpSeed
|
||||
?.let { Totp.generate(it) }
|
||||
?: run { Toast.makeText(requireContext(), "OTP unavailable", Toast.LENGTH_SHORT).show(); return }
|
||||
?: run { dialog.dismiss(); Toast.makeText(requireContext(), "OTP unavailable", Toast.LENGTH_SHORT).show(); return }
|
||||
|
||||
binding.btnTransfer.isEnabled = false
|
||||
(activity as? HomeActivity)?.setRefreshing(true)
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
@@ -1080,75 +1252,174 @@ class TransferFragment : Fragment() {
|
||||
sh.sar.basedbank.api.bml.BmlQrPayResult(false, errorMessage = e.message ?: "Payment failed")
|
||||
}
|
||||
}
|
||||
(activity as? HomeActivity)?.setRefreshing(false)
|
||||
if (_binding == null) return@launch
|
||||
|
||||
if (result == null) {
|
||||
dialog.dismiss()
|
||||
binding.btnTransfer.isEnabled = true
|
||||
Toast.makeText(requireContext(), "Failed to initiate payment", Toast.LENGTH_LONG).show()
|
||||
return@launch
|
||||
}
|
||||
if (result.success) {
|
||||
showBmlQrSuccessDialog(
|
||||
merchant = result.merchant.ifBlank { info.merchantName },
|
||||
amount = result.amount.ifBlank { "%.2f".format(amount) },
|
||||
currency = result.currency.ifBlank { info.currency }
|
||||
)
|
||||
showSuccessInDialog(
|
||||
dialog, frame,
|
||||
amountCurrency = result.currency.ifBlank { info.currency },
|
||||
amountValue = result.amount.ifBlank { "%.2f".format(amount) },
|
||||
fromName = src.accountBriefName,
|
||||
toName = result.merchant.ifBlank { info.merchantName }
|
||||
) {
|
||||
clearForm()
|
||||
(activity as? HomeActivity)?.triggerRefresh()
|
||||
}
|
||||
} else {
|
||||
dialog.dismiss()
|
||||
binding.btnTransfer.isEnabled = true
|
||||
Toast.makeText(requireContext(), result.errorMessage, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showBmlQrSuccessDialog(merchant: String, amount: String, currency: String) {
|
||||
private fun showProcessingInDialog(dialog: AlertDialog, frame: android.widget.FrameLayout) {
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE)?.visibility = View.GONE
|
||||
dialog.getButton(AlertDialog.BUTTON_NEGATIVE)?.visibility = View.GONE
|
||||
dialog.setCancelable(false)
|
||||
val ctx = requireContext()
|
||||
val dp = resources.displayMetrics.density
|
||||
val container = android.widget.LinearLayout(ctx).apply {
|
||||
orientation = android.widget.LinearLayout.VERTICAL
|
||||
gravity = android.view.Gravity.CENTER_HORIZONTAL
|
||||
setPadding((24 * dp).toInt(), (24 * dp).toInt(), (24 * dp).toInt(), (8 * dp).toInt())
|
||||
val spinner = CircularProgressDrawable(ctx).apply {
|
||||
setStyle(CircularProgressDrawable.LARGE)
|
||||
setColorSchemeColors(com.google.android.material.color.MaterialColors.getColor(
|
||||
requireView(), com.google.android.material.R.attr.colorPrimary, Color.GRAY))
|
||||
start()
|
||||
}
|
||||
container.addView(android.widget.ImageView(ctx).apply {
|
||||
setImageResource(R.drawable.ic_check_circle)
|
||||
setColorFilter(android.graphics.Color.parseColor("#4CAF50"))
|
||||
layoutParams = android.widget.LinearLayout.LayoutParams(
|
||||
(64 * dp).toInt(), (64 * dp).toInt()
|
||||
).apply { gravity = android.view.Gravity.CENTER_HORIZONTAL; bottomMargin = (16 * dp).toInt() }
|
||||
frame.removeAllViews()
|
||||
frame.addView(LinearLayout(ctx).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
setPadding((24 * dp).toInt(), (24 * dp).toInt(), (24 * dp).toInt(), (24 * dp).toInt())
|
||||
addView(ImageView(ctx).apply {
|
||||
setImageDrawable(spinner)
|
||||
layoutParams = LinearLayout.LayoutParams((48 * dp).toInt(), (48 * dp).toInt()).apply {
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
bottomMargin = (12 * dp).toInt()
|
||||
}
|
||||
})
|
||||
addView(TextView(ctx).apply {
|
||||
text = "Processing..."
|
||||
textSize = 16f
|
||||
gravity = Gravity.CENTER
|
||||
setTextColor(com.google.android.material.color.MaterialColors.getColor(
|
||||
requireView(), com.google.android.material.R.attr.colorOnSurface, Color.BLACK))
|
||||
})
|
||||
})
|
||||
container.addView(android.widget.TextView(ctx).apply {
|
||||
text = "$currency $amount"
|
||||
textSize = 28f
|
||||
setTypeface(null, android.graphics.Typeface.BOLD)
|
||||
setTextColor(com.google.android.material.color.MaterialColors.getColor(
|
||||
requireView(), com.google.android.material.R.attr.colorOnSurface, android.graphics.Color.BLACK))
|
||||
gravity = android.view.Gravity.CENTER
|
||||
layoutParams = android.widget.LinearLayout.LayoutParams(
|
||||
android.widget.LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
android.widget.LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply { gravity = android.view.Gravity.CENTER_HORIZONTAL; bottomMargin = (8 * dp).toInt() }
|
||||
})
|
||||
container.addView(android.widget.TextView(ctx).apply {
|
||||
text = merchant
|
||||
textSize = 14f
|
||||
setTextColor(com.google.android.material.color.MaterialColors.getColor(
|
||||
requireView(), com.google.android.material.R.attr.colorOnSurfaceVariant, android.graphics.Color.GRAY))
|
||||
gravity = android.view.Gravity.CENTER
|
||||
layoutParams = android.widget.LinearLayout.LayoutParams(
|
||||
android.widget.LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
android.widget.LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply { gravity = android.view.Gravity.CENTER_HORIZONTAL }
|
||||
})
|
||||
MaterialAlertDialogBuilder(ctx)
|
||||
.setTitle(R.string.bml_qr_payment_success)
|
||||
.setView(container)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun showSuccessInDialog(
|
||||
dialog: AlertDialog,
|
||||
frame: android.widget.FrameLayout,
|
||||
amountCurrency: String,
|
||||
amountValue: String,
|
||||
fromName: String,
|
||||
toName: String,
|
||||
onDone: () -> Unit
|
||||
) {
|
||||
val ctx = requireContext()
|
||||
val dp = resources.displayMetrics.density
|
||||
val colorOnSurface = com.google.android.material.color.MaterialColors.getColor(
|
||||
requireView(), com.google.android.material.R.attr.colorOnSurface, Color.BLACK)
|
||||
val colorMuted = com.google.android.material.color.MaterialColors.getColor(
|
||||
requireView(), com.google.android.material.R.attr.colorOnSurfaceVariant, Color.GRAY)
|
||||
val colorPrimary = com.google.android.material.color.MaterialColors.getColor(
|
||||
requireView(), com.google.android.material.R.attr.colorPrimary, Color.BLUE)
|
||||
val MATCH = LinearLayout.LayoutParams.MATCH_PARENT
|
||||
val WRAP = LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
|
||||
frame.removeAllViews()
|
||||
frame.addView(LinearLayout(ctx).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
setPadding((24 * dp).toInt(), (20 * dp).toInt(), (24 * dp).toInt(), (8 * dp).toInt())
|
||||
|
||||
// Checkmark
|
||||
addView(ImageView(ctx).apply {
|
||||
setImageResource(R.drawable.ic_check_circle)
|
||||
setColorFilter(Color.parseColor("#4CAF50"))
|
||||
layoutParams = LinearLayout.LayoutParams((64 * dp).toInt(), (64 * dp).toInt()).apply {
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
bottomMargin = (16 * dp).toInt()
|
||||
}
|
||||
})
|
||||
|
||||
// Currency + amount
|
||||
addView(LinearLayout(ctx).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
layoutParams = LinearLayout.LayoutParams(MATCH, WRAP).apply {
|
||||
bottomMargin = (16 * dp).toInt()
|
||||
}
|
||||
addView(TextView(ctx).apply {
|
||||
text = "$amountCurrency "
|
||||
textSize = 16f
|
||||
setTextColor(colorMuted)
|
||||
layoutParams = LinearLayout.LayoutParams(WRAP, WRAP)
|
||||
})
|
||||
addView(TextView(ctx).apply {
|
||||
text = amountValue
|
||||
textSize = 28f
|
||||
setTypeface(null, Typeface.BOLD)
|
||||
setTextColor(colorPrimary)
|
||||
})
|
||||
})
|
||||
|
||||
// From row
|
||||
addView(LinearLayout(ctx).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
layoutParams = LinearLayout.LayoutParams(MATCH, WRAP)
|
||||
addView(TextView(ctx).apply {
|
||||
text = "From "
|
||||
textSize = 12f
|
||||
setTextColor(colorMuted)
|
||||
layoutParams = LinearLayout.LayoutParams(WRAP, WRAP)
|
||||
})
|
||||
addView(TextView(ctx).apply {
|
||||
text = fromName
|
||||
textSize = 13f
|
||||
setTypeface(null, Typeface.BOLD)
|
||||
setTextColor(colorOnSurface)
|
||||
gravity = Gravity.CENTER
|
||||
})
|
||||
})
|
||||
|
||||
// To row
|
||||
addView(LinearLayout(ctx).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
layoutParams = LinearLayout.LayoutParams(MATCH, WRAP).apply {
|
||||
topMargin = (4 * dp).toInt()
|
||||
}
|
||||
addView(TextView(ctx).apply {
|
||||
text = "To "
|
||||
textSize = 12f
|
||||
setTextColor(colorMuted)
|
||||
layoutParams = LinearLayout.LayoutParams(WRAP, WRAP)
|
||||
})
|
||||
addView(TextView(ctx).apply {
|
||||
text = toName
|
||||
textSize = 13f
|
||||
setTypeface(null, Typeface.BOLD)
|
||||
setTextColor(colorOnSurface)
|
||||
gravity = Gravity.CENTER
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
val okBtn = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
|
||||
okBtn?.visibility = View.VISIBLE
|
||||
okBtn?.text = "OK"
|
||||
okBtn?.setOnClickListener { dialog.dismiss(); onDone() }
|
||||
}
|
||||
|
||||
|
||||
private fun doMibTransfer(
|
||||
src: BankAccount,
|
||||
destAccount: String,
|
||||
@@ -1718,6 +1989,7 @@ class TransferFragment : Fragment() {
|
||||
requireActivity().title = getString(R.string.transfer)
|
||||
}
|
||||
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
|
||||
Reference in New Issue
Block a user