From 1753d648bdb46088e5ebed56166258aa7325de9e Mon Sep 17 00:00:00 2001 From: Shihaam Abdul Rahman Date: Mon, 18 May 2026 05:31:20 +0500 Subject: [PATCH] loading indicator for account info fetch and tranfer --- app/build.gradle.kts | 3 +++ .../ui/home/AddContactSheetFragment.kt | 24 +++++++++++++++-- .../sar/basedbank/ui/home/TransferFragment.kt | 27 ++++++++++++++++--- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c676404..2034884 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -64,6 +64,9 @@ dependencies { // RecyclerView for accounts list implementation("androidx.recyclerview:recyclerview:1.3.2") + // CircularProgressDrawable for spinning search icons + implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") + // OkHttp for API calls implementation("com.squareup.okhttp3:okhttp:4.11.0") diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/AddContactSheetFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/AddContactSheetFragment.kt index 2e0c35a..bfa5aab 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/AddContactSheetFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/AddContactSheetFragment.kt @@ -14,7 +14,9 @@ import android.view.ViewGroup import android.widget.ArrayAdapter import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.content.ContextCompat import androidx.fragment.app.activityViewModels +import androidx.swiperefreshlayout.widget.CircularProgressDrawable import androidx.lifecycle.lifecycleScope import com.google.android.material.bottomsheet.BottomSheetDialogFragment import sh.sar.basedbank.util.ContactsCache @@ -129,6 +131,22 @@ class AddContactSheetFragment : BottomSheetDialogFragment() { } } + private fun startLookupLoading() { + val spinner = CircularProgressDrawable(requireContext()).apply { + setStyle(CircularProgressDrawable.DEFAULT) + setColorSchemeColors(com.google.android.material.color.MaterialColors.getColor( + requireView(), com.google.android.material.R.attr.colorPrimary, Color.GRAY)) + start() + } + binding.tilAccount.endIconDrawable = spinner + binding.tilAccount.isEnabled = false + } + + private fun stopLookupLoading() { + binding.tilAccount.isEnabled = true + binding.tilAccount.endIconDrawable = ContextCompat.getDrawable(requireContext(), android.R.drawable.ic_menu_search) + } + private fun setupAccountSearch() { binding.tilAccount.setEndIconOnClickListener { performLookup() } } @@ -167,7 +185,7 @@ class AddContactSheetFragment : BottomSheetDialogFragment() { return } - binding.tilAccount.isEnabled = false + startLookupLoading() binding.tilDestination.isEnabled = false binding.btnSave.isEnabled = false @@ -175,7 +193,7 @@ class AddContactSheetFragment : BottomSheetDialogFragment() { val result = withContext(Dispatchers.IO) { if (dest.isBml) lookupForBml(input) else lookupForMib(dest, input) } - binding.tilAccount.isEnabled = true + stopLookupLoading() binding.tilDestination.isEnabled = true if (result != null) { showLookupResult(result, input) @@ -341,6 +359,7 @@ class AddContactSheetFragment : BottomSheetDialogFragment() { binding.tilAlias.error = null binding.btnSave.isEnabled = false + binding.btnSave.text = "Saving..." viewLifecycleOwner.lifecycleScope.launch { val success = withContext(Dispatchers.IO) { @@ -352,6 +371,7 @@ class AddContactSheetFragment : BottomSheetDialogFragment() { dismiss() } else { binding.btnSave.isEnabled = true + binding.btnSave.text = "Save" Toast.makeText(requireContext(), R.string.contact_save_failed, Toast.LENGTH_SHORT).show() } } diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt index d884228..1f502a5 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt @@ -23,6 +23,7 @@ import androidx.biometric.BiometricManager import androidx.biometric.BiometricPrompt import androidx.core.content.ContextCompat import androidx.core.widget.addTextChangedListener +import androidx.swiperefreshlayout.widget.CircularProgressDrawable import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.lifecycleScope @@ -159,6 +160,22 @@ class TransferFragment : Fragment() { } } + private fun startLookupLoading() { + val spinner = CircularProgressDrawable(requireContext()).apply { + setStyle(CircularProgressDrawable.DEFAULT) + setColorSchemeColors(com.google.android.material.color.MaterialColors.getColor( + requireView(), com.google.android.material.R.attr.colorPrimary, Color.GRAY)) + start() + } + binding.tilTo.endIconDrawable = spinner + binding.tilTo.isEnabled = false + } + + private fun stopLookupLoading() { + binding.tilTo.isEnabled = true + binding.tilTo.endIconDrawable = ContextCompat.getDrawable(requireContext(), android.R.drawable.ic_menu_search) + } + private fun setupFromDropdown() { binding.btnClearFromInfo.setOnClickListener { selectedAccount = null @@ -313,7 +330,7 @@ class TransferFragment : Fragment() { val isBmlSource = selectedAccount?.profileType?.startsWith("BML") == true - binding.tilTo.isEnabled = false + startLookupLoading() viewLifecycleOwner.lifecycleScope.launch { var errorMsg: String? = null @@ -357,7 +374,7 @@ class TransferFragment : Fragment() { } } } - binding.tilTo.isEnabled = true + stopLookupLoading() if (info != null) { val accounts = viewModel.accounts.value ?: emptyList() val matchedAcc = accounts.firstOrNull { it.accountNumber == info.accountNumber } @@ -392,7 +409,7 @@ class TransferFragment : Fragment() { } private fun lookupFahipayTarget(number: String) { - binding.tilTo.isEnabled = false + startLookupLoading() viewLifecycleOwner.lifecycleScope.launch { data class LookupResult( val dhiraagu: DhiraaguClient.Result, @@ -419,7 +436,7 @@ class TransferFragment : Fragment() { LookupResult(d, o) } } - binding.tilTo.isEnabled = true + stopLookupLoading() val dhiraaguName = result.dhiraagu.ownerName.takeIf { it.isNotBlank() } @@ -586,6 +603,7 @@ class TransferFragment : Fragment() { val doTransfer: () -> Unit = { binding.btnTransfer.isEnabled = false + (activity as? HomeActivity)?.setRefreshing(true) viewLifecycleOwner.lifecycleScope.launch { val (ok, msg, receipt) = withContext(Dispatchers.IO) { if (!isSrcBml) { @@ -595,6 +613,7 @@ class TransferFragment : Fragment() { } } binding.btnTransfer.isEnabled = true + (activity as? HomeActivity)?.setRefreshing(false) if (ok && receipt != null) { clearForm() val activity = requireActivity() as HomeActivity