optimize bank login screens, add support for otpauth://totp/ URI
All checks were successful
Auto Tag on Version Change / check-version (push) Successful in 3s

This commit is contained in:
2026-05-18 23:49:42 +05:00
parent 1a58ce8b54
commit b35f44f35b
2 changed files with 46 additions and 8 deletions

View File

@@ -67,11 +67,27 @@ class CredentialsFragment : Fragment() {
}
}
binding.btnLogin.isEnabled = false
binding.btnLogin.setOnClickListener { attemptLogin() }
val loginFieldWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) { updateLoginButtonState() }
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
}
binding.etUsername.addTextChangedListener(loginFieldWatcher)
binding.etPassword.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) { updateLoginButtonState(); updateOtpDisplay() }
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
})
if (bankType != "FAHIPAY") {
binding.etOtpSeed.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) { updateOtpDisplay() }
override fun afterTextChanged(s: Editable?) {
updateOtpDisplay()
updateLoginButtonState()
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
})
@@ -88,10 +104,33 @@ class CredentialsFragment : Fragment() {
otpHandler.removeCallbacks(otpRunnable)
}
private fun resolveOtpSeed(input: String): String {
val secret = if (input.startsWith("otpauth://totp/"))
android.net.Uri.parse(input).getQueryParameter("secret") ?: input
else
input
return secret.replace("\\s".toRegex(), "").replace("-", "").uppercase()
}
private fun updateLoginButtonState() {
val username = binding.etUsername.text.toString().trim()
val password = binding.etPassword.text.toString()
val otpSeed = resolveOtpSeed(binding.etOtpSeed.text.toString().trim())
binding.btnLogin.isEnabled = when (bankType) {
"FAHIPAY" -> username.isNotEmpty() && password.isNotEmpty()
else -> username.isNotEmpty() && password.isNotEmpty() && otpSeed.isNotEmpty() && password != otpSeed
}
}
private fun updateOtpDisplay() {
val seed = binding.etOtpSeed.text.toString().trim()
val seed = resolveOtpSeed(binding.etOtpSeed.text.toString().trim())
if (seed.isEmpty()) {
binding.cardOtp.visibility = View.GONE
binding.cardOtp.visibility = View.INVISIBLE
return
}
val password = binding.etPassword.text.toString()
if (seed == password || seed.matches(Regex("\\d{6}"))) {
binding.cardOtp.visibility = View.INVISIBLE
return
}
try {
@@ -104,7 +143,7 @@ class CredentialsFragment : Fragment() {
binding.otpTimer.progress = remaining
binding.cardOtp.visibility = View.VISIBLE
} catch (e: Exception) {
binding.cardOtp.visibility = View.GONE
binding.cardOtp.visibility = View.INVISIBLE
}
}
@@ -116,7 +155,7 @@ class CredentialsFragment : Fragment() {
val username = binding.etUsername.text.toString().trim()
val password = binding.etPassword.text.toString()
val otpSeed = binding.etOtpSeed.text.toString().trim()
val otpSeed = resolveOtpSeed(binding.etOtpSeed.text.toString().trim())
if (username.isEmpty() || password.isEmpty() || otpSeed.isEmpty()) {
binding.tvError.text = "Please fill in all fields"
@@ -173,7 +212,7 @@ class CredentialsFragment : Fragment() {
private fun attemptBmlLogin() {
val username = binding.etUsername.text.toString().trim()
val password = binding.etPassword.text.toString()
val otpSeed = binding.etOtpSeed.text.toString().trim()
val otpSeed = resolveOtpSeed(binding.etOtpSeed.text.toString().trim())
if (username.isEmpty() || password.isEmpty() || otpSeed.isEmpty()) {
binding.tvError.text = "Please fill in all fields"

View File

@@ -80,7 +80,6 @@
android:hint="@string/otp_seed"
android:layout_marginBottom="8dp"
app:endIconMode="password_toggle"
app:helperText="@string/otp_seed_hint"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etOtpSeed"
@@ -116,7 +115,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:visibility="gone"
android:visibility="invisible"
app:cardBackgroundColor="?attr/colorSecondaryContainer"
app:cardCornerRadius="12dp"
app:cardElevation="0dp">