From 3a5b9459a9ebfe35d6cf21ff09269c9e024dc5ac Mon Sep 17 00:00:00 2001 From: Shihaam Abdul Rahman Date: Tue, 19 May 2026 18:21:36 +0500 Subject: [PATCH] customize quick actions and bottom bar --- .../sar/basedbank/ui/home/ContactsFragment.kt | 6 +- .../basedbank/ui/home/DashboardFragment.kt | 23 ++- .../sh/sar/basedbank/ui/home/HomeActivity.kt | 63 ++++++-- .../sh/sar/basedbank/ui/home/MoreFragment.kt | 21 +-- .../sar/basedbank/ui/home/NavCustomization.kt | 61 ++++++++ .../basedbank/ui/home/NavMoreSheetFragment.kt | 11 +- .../ui/home/SettingsAppearanceFragment.kt | 134 +++++++++++++++++- .../sar/basedbank/ui/home/TransferFragment.kt | 7 +- app/src/main/res/drawable/ic_drag_handle.xml | 10 ++ .../main/res/layout/fragment_dashboard.xml | 51 ++++--- .../layout/fragment_settings_appearance.xml | 63 ++++++++ app/src/main/res/layout/item_nav_slot.xml | 28 ++++ app/src/main/res/layout/sheet_nav_more.xml | 4 +- app/src/main/res/values-b+dv/strings.xml | 8 ++ app/src/main/res/values/strings.xml | 7 + 15 files changed, 434 insertions(+), 63 deletions(-) create mode 100644 app/src/main/java/sh/sar/basedbank/ui/home/NavCustomization.kt create mode 100644 app/src/main/res/drawable/ic_drag_handle.xml create mode 100644 app/src/main/res/layout/item_nav_slot.xml diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/ContactsFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/ContactsFragment.kt index ded081f..37df3d6 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/ContactsFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/ContactsFragment.kt @@ -8,7 +8,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast -import androidx.appcompat.app.AlertDialog +import com.google.android.material.dialog.MaterialAlertDialogBuilder import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.core.widget.addTextChangedListener @@ -177,11 +177,11 @@ class ContactsFragment : Fragment() { } private fun confirmDelete(contact: ContactDisplay) { - AlertDialog.Builder(requireContext()) + MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.contact_delete_title) .setMessage(getString(R.string.contact_delete_message, contact.name)) .setPositiveButton(R.string.contact_delete) { _, _ -> deleteContact(contact) } - .setNegativeButton(android.R.string.cancel, null) + .setNegativeButton(R.string.cancel, null) .show() } diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt index 04744b5..939a391 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/DashboardFragment.kt @@ -1,10 +1,11 @@ package sh.sar.basedbank.ui.home +import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.Toast +import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.fragment.app.Fragment @@ -41,17 +42,25 @@ class DashboardFragment : Fragment() { insets } - binding.btnTransfer.setOnClickListener { - (requireActivity() as HomeActivity).navigateTo(R.id.nav_transfer) - } - binding.btnPayMvQr.setOnClickListener { - Toast.makeText(requireContext(), R.string.work_in_progress, Toast.LENGTH_SHORT).show() - } } override fun onResume() { super.onResume() requireActivity().title = getString(R.string.nav_dashboard) + refreshQuickActions() + } + + private fun refreshQuickActions() { + val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE) + val ids = NavCustomization.getQuickActions(prefs) + listOf(binding.btnQuickAction1, binding.btnQuickAction2).forEachIndexed { i, btn -> + val def = NavCustomization.ALL_SWAPPABLE.find { it.id == ids[i] } + if (def != null) { + btn.setText(def.titleRes) + btn.icon = ContextCompat.getDrawable(requireContext(), def.iconRes) + } + btn.setOnClickListener { (requireActivity() as HomeActivity).navigateTo(ids[i]) } + } } private fun updateBalances(accounts: List) { diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt b/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt index aef216e..7374b4a 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt @@ -9,7 +9,9 @@ import android.os.Looper import android.view.Menu import android.view.MenuItem import android.view.View +import com.google.android.material.navigation.NavigationBarView import android.widget.Toast +import sh.sar.basedbank.ui.home.NavCustomization import androidx.appcompat.app.AlertDialog import com.google.android.material.dialog.MaterialAlertDialogBuilder import androidx.activity.viewModels @@ -108,14 +110,21 @@ class HomeActivity : AppCompatActivity() { binding.bottomNavigation.setOnItemSelectedListener { item -> if (suppressBottomNavCallback) return@setOnItemSelectedListener true - when (item.itemId) { - R.id.nav_dashboard -> { show(DashboardFragment()); true } - R.id.nav_accounts -> { show(AccountsFragment()); true } - R.id.nav_contacts -> { show(ContactsFragment()); true } - R.id.nav_transfer -> { show(TransferFragment()); true } - R.id.nav_more -> { show(MoreFragment()); true } - else -> false + val frag = when (item.itemId) { + R.id.nav_dashboard -> DashboardFragment() + R.id.nav_accounts -> AccountsFragment() + R.id.nav_contacts -> ContactsFragment() + R.id.nav_transfer -> TransferFragment() + R.id.nav_more -> MoreFragment() + R.id.nav_transfer_history -> TransferHistoryFragment() + R.id.nav_finances -> FinancingFragment() + R.id.nav_otp -> OtpFragment() + R.id.nav_settings -> SettingsFragment() + else -> null } + if (frag != null) show(frag) + else Toast.makeText(this, R.string.work_in_progress, Toast.LENGTH_SHORT).show() + true } applyNavMode() @@ -210,12 +219,15 @@ class HomeActivity : AppCompatActivity() { } fun applyNavMode() { - val isBottom = getSharedPreferences("prefs", MODE_PRIVATE).getBoolean("bottom_nav", false) + val prefs = getSharedPreferences("prefs", MODE_PRIVATE) + val isBottom = prefs.getBoolean("bottom_nav", false) if (isBottom) { binding.drawerLayout.setDrawerLockMode(androidx.drawerlayout.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED) toggle.isDrawerIndicatorEnabled = false supportActionBar?.setDisplayHomeAsUpEnabled(false) binding.bottomNavigation.visibility = View.VISIBLE + rebuildBottomNav(prefs) + applyNavLabelVisibility() } else { binding.drawerLayout.setDrawerLockMode(androidx.drawerlayout.widget.DrawerLayout.LOCK_MODE_UNLOCKED) toggle.isDrawerIndicatorEnabled = true @@ -224,6 +236,27 @@ class HomeActivity : AppCompatActivity() { } } + fun rebuildBottomNav(prefs: android.content.SharedPreferences = getSharedPreferences("prefs", MODE_PRIVATE)) { + val slots = NavCustomization.getSlots(prefs) + val menu = binding.bottomNavigation.menu + menu.clear() + menu.add(Menu.NONE, R.id.nav_dashboard, 0, R.string.nav_dashboard) + .setIcon(R.drawable.ic_nav_dashboard) + slots.forEachIndexed { i, id -> + val item = NavCustomization.ALL_SWAPPABLE.find { it.id == id } ?: return@forEachIndexed + menu.add(Menu.NONE, item.id, i + 1, item.titleRes).setIcon(item.iconRes) + } + menu.add(Menu.NONE, R.id.nav_more, 4, R.string.nav_more) + .setIcon(R.drawable.ic_nav_more) + } + + fun applyNavLabelVisibility() { + val showLabels = getSharedPreferences("prefs", MODE_PRIVATE).getBoolean("bottom_nav_show_labels", true) + binding.bottomNavigation.labelVisibilityMode = + if (showLabels) NavigationBarView.LABEL_VISIBILITY_LABELED + else NavigationBarView.LABEL_VISIBILITY_AUTO + } + fun navigateTo(itemId: Int, fragment: Fragment? = null) { val dest = fragment ?: when (itemId) { R.id.nav_dashboard -> DashboardFragment() @@ -238,11 +271,15 @@ class HomeActivity : AppCompatActivity() { } show(dest) 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 - binding.bottomNavigation.selectedItemId = itemId - suppressBottomNavCallback = false + if (binding.bottomNavigation.visibility == View.VISIBLE) { + val bottomNavIds = (0 until binding.bottomNavigation.menu.size()) + .map { binding.bottomNavigation.menu.getItem(it).itemId }.toSet() + val selectId = if (itemId in bottomNavIds) itemId else if (R.id.nav_more in bottomNavIds) R.id.nav_more else null + if (selectId != null) { + suppressBottomNavCallback = true + binding.bottomNavigation.selectedItemId = selectId + suppressBottomNavCallback = false + } } } diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/MoreFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/MoreFragment.kt index baf65a3..c32b2a1 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/MoreFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/MoreFragment.kt @@ -1,5 +1,6 @@ package sh.sar.basedbank.ui.home +import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -7,35 +8,23 @@ import android.view.ViewGroup import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView -import androidx.annotation.DrawableRes -import androidx.annotation.StringRes import androidx.fragment.app.Fragment import sh.sar.basedbank.R 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), - NavItem(R.id.nav_card_settings, R.drawable.ic_nav_card, R.string.nav_card_settings), - NavItem(R.id.nav_otp, R.drawable.ic_nav_otp, R.string.nav_otp), - NavItem(R.id.nav_settings, R.drawable.ic_nav_settings, R.string.nav_settings), - ) - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = inflater.inflate(R.layout.fragment_more, container, false) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE) + val items = NavCustomization.getMoreItems(prefs) val list = view.findViewById(R.id.moreList) val inflater = LayoutInflater.from(requireContext()) for (item in items) { val row = inflater.inflate(R.layout.item_more_nav, list, false) - row.findViewById(R.id.ivIcon).setImageResource(item.icon) - row.findViewById(R.id.tvLabel).setText(item.title) + row.findViewById(R.id.ivIcon).setImageResource(item.iconRes) + row.findViewById(R.id.tvLabel).setText(item.titleRes) row.setOnClickListener { (requireActivity() as HomeActivity).navigateTo(item.id) } list.addView(row) } diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/NavCustomization.kt b/app/src/main/java/sh/sar/basedbank/ui/home/NavCustomization.kt new file mode 100644 index 0000000..ff936c8 --- /dev/null +++ b/app/src/main/java/sh/sar/basedbank/ui/home/NavCustomization.kt @@ -0,0 +1,61 @@ +package sh.sar.basedbank.ui.home + +import android.content.SharedPreferences +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import sh.sar.basedbank.R + +object NavCustomization { + + data class NavItemDef( + val id: Int, + @DrawableRes val iconRes: Int, + @StringRes val titleRes: Int + ) + + /** All items that can occupy either a bottom nav slot or the "More" screen. */ + val ALL_SWAPPABLE = listOf( + NavItemDef(R.id.nav_accounts, R.drawable.ic_nav_accounts, R.string.nav_accounts), + NavItemDef(R.id.nav_contacts, R.drawable.ic_contacts, R.string.nav_contacts), + NavItemDef(R.id.nav_transfer, R.drawable.ic_send, R.string.transfer), + NavItemDef(R.id.nav_pay_mv_qr, R.drawable.ic_qr_scan, R.string.pay_mv_qr), + NavItemDef(R.id.nav_activities, R.drawable.ic_nav_activities, R.string.nav_activities), + NavItemDef(R.id.nav_transfer_history, R.drawable.ic_nav_transfer_history, R.string.nav_transfer_history), + NavItemDef(R.id.nav_finances, R.drawable.ic_nav_finances, R.string.nav_finances), + NavItemDef(R.id.nav_card_settings, R.drawable.ic_nav_card, R.string.nav_card_settings), + NavItemDef(R.id.nav_otp, R.drawable.ic_nav_otp, R.string.nav_otp), + NavItemDef(R.id.nav_settings, R.drawable.ic_nav_settings, R.string.nav_settings), + ) + + fun getSlots(prefs: SharedPreferences): List = listOf( + prefs.getInt("bottom_nav_slot_1", R.id.nav_accounts), + prefs.getInt("bottom_nav_slot_2", R.id.nav_contacts), + prefs.getInt("bottom_nav_slot_3", R.id.nav_transfer), + ) + + fun saveSlots(prefs: SharedPreferences, slots: List) { + prefs.edit() + .putInt("bottom_nav_slot_1", slots[0]) + .putInt("bottom_nav_slot_2", slots[1]) + .putInt("bottom_nav_slot_3", slots[2]) + .apply() + } + + fun getQuickActions(prefs: SharedPreferences): List = listOf( + prefs.getInt("quick_action_1", R.id.nav_transfer), + prefs.getInt("quick_action_2", R.id.nav_pay_mv_qr), + ) + + fun saveQuickActions(prefs: SharedPreferences, ids: List) { + prefs.edit() + .putInt("quick_action_1", ids[0]) + .putInt("quick_action_2", ids[1]) + .apply() + } + + /** Items that belong in the "More" screen — those not occupying a bottom nav slot. */ + fun getMoreItems(prefs: SharedPreferences): List { + val slots = getSlots(prefs).toSet() + return ALL_SWAPPABLE.filter { it.id !in slots } + } +} diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/NavMoreSheetFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/NavMoreSheetFragment.kt index ee46f57..42f5e9b 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/NavMoreSheetFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/NavMoreSheetFragment.kt @@ -1,7 +1,9 @@ package sh.sar.basedbank.ui.home +import android.content.Context import android.os.Bundle import android.view.LayoutInflater +import android.view.Menu import android.view.View import android.view.ViewGroup import com.google.android.material.bottomsheet.BottomSheetDialogFragment @@ -16,7 +18,14 @@ class NavMoreSheetFragment : BottomSheetDialogFragment() { inflater.inflate(R.layout.sheet_nav_more, container, false) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - view.findViewById(R.id.navMoreView).setNavigationItemSelectedListener { item -> + val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE) + val items = NavCustomization.getMoreItems(prefs) + val navView = view.findViewById(R.id.navMoreView) + navView.menu.clear() + items.forEachIndexed { i, item -> + navView.menu.add(Menu.NONE, item.id, i, item.titleRes).setIcon(item.iconRes) + } + navView.setNavigationItemSelectedListener { item -> dismiss() onNavigate?.invoke(item.itemId) true diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/SettingsAppearanceFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/SettingsAppearanceFragment.kt index 5f4c2da..778f3d9 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/SettingsAppearanceFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/SettingsAppearanceFragment.kt @@ -1,29 +1,45 @@ package sh.sar.basedbank.ui.home import android.content.Context +import android.content.SharedPreferences import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.ScrollView +import android.widget.TextView import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate.setApplicationLocales import androidx.core.os.LocaleListCompat import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.dialog.MaterialAlertDialogBuilder import sh.sar.basedbank.R import sh.sar.basedbank.databinding.FragmentSettingsAppearanceBinding +import java.util.Collections class SettingsAppearanceFragment : Fragment() { private var _binding: FragmentSettingsAppearanceBinding? = null private val binding get() = _binding!! + private lateinit var prefs: SharedPreferences + private val slots = mutableListOf() + private val quickActions = mutableListOf() + private lateinit var slotAdapter: NavItemAdapter + private lateinit var quickActionAdapter: NavItemAdapter + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = FragmentSettingsAppearanceBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE) + prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE) // Navigation mode val isBottom = prefs.getBoolean("bottom_nav", false) @@ -32,8 +48,35 @@ class SettingsAppearanceFragment : Fragment() { if (!isChecked) return@addOnButtonCheckedListener prefs.edit().putBoolean("bottom_nav", checkedId == R.id.btnNavBottom).apply() (activity as? HomeActivity)?.applyNavMode() + updateShortcutsVisibility() } + // Quick actions + quickActions.clear() + quickActions.addAll(NavCustomization.getQuickActions(prefs)) + quickActionAdapter = NavItemAdapter(quickActions) { + NavCustomization.saveQuickActions(prefs, quickActions) + } + setupNavItemRecyclerView(binding.rvQuickActions, quickActionAdapter, quickActions) + + // Bottom bar shortcuts + slots.clear() + slots.addAll(NavCustomization.getSlots(prefs)) + slotAdapter = NavItemAdapter(slots) { + NavCustomization.saveSlots(prefs, slots) + (activity as? HomeActivity)?.rebuildBottomNav(prefs) + } + setupNavItemRecyclerView(binding.rvNavSlots, slotAdapter, slots) + // Show labels toggle + val showLabels = prefs.getBoolean("bottom_nav_show_labels", true) + binding.switchShowLabels.isChecked = showLabels + binding.switchShowLabels.setOnCheckedChangeListener { _, checked -> + prefs.edit().putBoolean("bottom_nav_show_labels", checked).apply() + (activity as? HomeActivity)?.applyNavLabelVisibility() + } + + updateShortcutsVisibility() + // Theme val saved = prefs.getString("theme", "system") binding.themeToggle.check(when (saved) { @@ -63,6 +106,95 @@ class SettingsAppearanceFragment : Fragment() { } } + private fun setupNavItemRecyclerView( + rv: RecyclerView, + adapter: NavItemAdapter, + items: MutableList + ) { + rv.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false) + rv.adapter = adapter + ItemTouchHelper(object : ItemTouchHelper.SimpleCallback( + ItemTouchHelper.START or ItemTouchHelper.END, 0 + ) { + override fun onMove( + rv: RecyclerView, + from: RecyclerView.ViewHolder, + to: RecyclerView.ViewHolder + ): Boolean { + val fromPos = from.adapterPosition + val toPos = to.adapterPosition + Collections.swap(items, fromPos, toPos) + adapter.notifyItemMoved(fromPos, toPos) + adapter.onSave() + return true + } + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {} + }).attachToRecyclerView(rv) + } + + private fun updateShortcutsVisibility() { + val isBottom = prefs.getBoolean("bottom_nav", false) + binding.sectionBottomBarShortcuts.alpha = if (isBottom) 1f else 0.38f + } + + private fun showItemPicker(items: MutableList, slotIndex: Int, adapter: NavItemAdapter) { + if (items === slots && !prefs.getBoolean("bottom_nav", false)) return + val ctx = requireContext() + val otherIds = items.filterIndexed { i, _ -> i != slotIndex }.toSet() + val available = NavCustomization.ALL_SWAPPABLE.filter { it.id !in otherIds } + val listLayout = LinearLayout(ctx).apply { orientation = LinearLayout.VERTICAL } + val rows = available.map { item -> + LayoutInflater.from(ctx).inflate(R.layout.item_more_nav, listLayout, false).also { row -> + row.findViewById(R.id.ivIcon).setImageResource(item.iconRes) + row.findViewById(R.id.tvLabel).setText(item.titleRes) + listLayout.addView(row) + } + } + val scroll = ScrollView(ctx).apply { addView(listLayout) } + var dialog: androidx.appcompat.app.AlertDialog? = null + dialog = MaterialAlertDialogBuilder(ctx) + .setTitle(R.string.settings_bottom_bar_select) + .setView(scroll) + .setNegativeButton(R.string.cancel, null) + .show() + available.forEachIndexed { i, item -> + rows[i].setOnClickListener { + items[slotIndex] = item.id + adapter.onSave() + adapter.notifyItemChanged(slotIndex) + dialog?.dismiss() + } + } + } + + private inner class NavItemAdapter( + val items: MutableList, + val onSave: () -> Unit + ) : RecyclerView.Adapter() { + + inner class VH(view: View) : RecyclerView.ViewHolder(view) { + val ivNavIcon: ImageView = view.findViewById(R.id.ivNavIcon) + val tvNavLabel: TextView = view.findViewById(R.id.tvNavLabel) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH { + val view = LayoutInflater.from(parent.context).inflate(R.layout.item_nav_slot, parent, false) + val itemWidth = if (parent.measuredWidth > 0) parent.measuredWidth / items.size + else RecyclerView.LayoutParams.WRAP_CONTENT + view.layoutParams = RecyclerView.LayoutParams(itemWidth, RecyclerView.LayoutParams.WRAP_CONTENT) + return VH(view) + } + + override fun getItemCount() = items.size + + override fun onBindViewHolder(holder: VH, position: Int) { + val def = NavCustomization.ALL_SWAPPABLE.find { it.id == items[position] } ?: return + holder.ivNavIcon.setImageResource(def.iconRes) + holder.tvNavLabel.setText(def.titleRes) + holder.itemView.setOnClickListener { showItemPicker(items, holder.adapterPosition, this) } + } + } + override fun onResume() { super.onResume() requireActivity().title = getString(R.string.settings_appearance) 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 047c83c..09a2047 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 @@ -19,6 +19,7 @@ import android.widget.LinearLayout import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AlertDialog +import com.google.android.material.dialog.MaterialAlertDialogBuilder import androidx.biometric.BiometricManager import androidx.biometric.BiometricPrompt import androidx.core.content.ContextCompat @@ -590,10 +591,10 @@ class TransferFragment : Fragment() { if (isSrcBml && isDestMib && currency == "USD") { val hasBmlContact = allContacts.any { it.benefCategoryId == "BML" && it.benefAccount == resolvedAccountNumber } if (!hasBmlContact) { - AlertDialog.Builder(requireContext()) + MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.transfer_bml_contact_required_title) .setMessage(R.string.transfer_bml_contact_required_msg) - .setPositiveButton("OK", null) + .setPositiveButton(R.string.close, null) .show() return } @@ -637,7 +638,7 @@ class TransferFragment : Fragment() { } } - val dialogBuilder = AlertDialog.Builder(requireContext()) + val dialogBuilder = MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.transfer) .setPositiveButton(R.string.transfer_confirm) { _, _ -> doTransfer() } .setNegativeButton(android.R.string.cancel, null) diff --git a/app/src/main/res/drawable/ic_drag_handle.xml b/app/src/main/res/drawable/ic_drag_handle.xml new file mode 100644 index 0000000..b38e461 --- /dev/null +++ b/app/src/main/res/drawable/ic_drag_handle.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml index a56c5c1..eb2cf94 100644 --- a/app/src/main/res/layout/fragment_dashboard.xml +++ b/app/src/main/res/layout/fragment_dashboard.xml @@ -172,33 +172,52 @@ - + - + android:text="@string/dashboard_quick_actions" + android:textAppearance="?attr/textAppearanceLabelMedium" + android:textColor="?attr/colorOnSurfaceVariant" + android:layout_marginBottom="8dp" /> - + android:orientation="horizontal"> + + + + + + diff --git a/app/src/main/res/layout/fragment_settings_appearance.xml b/app/src/main/res/layout/fragment_settings_appearance.xml index e29467b..6cddf24 100644 --- a/app/src/main/res/layout/fragment_settings_appearance.xml +++ b/app/src/main/res/layout/fragment_settings_appearance.xml @@ -45,6 +45,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/sheet_nav_more.xml b/app/src/main/res/layout/sheet_nav_more.xml index be8be63..d93d9dc 100644 --- a/app/src/main/res/layout/sheet_nav_more.xml +++ b/app/src/main/res/layout/sheet_nav_more.xml @@ -1,8 +1,6 @@ + android:layout_height="wrap_content" /> diff --git a/app/src/main/res/values-b+dv/strings.xml b/app/src/main/res/values-b+dv/strings.xml index 24268c7..6b0565b 100644 --- a/app/src/main/res/values-b+dv/strings.xml +++ b/app/src/main/res/values-b+dv/strings.xml @@ -79,6 +79,7 @@ ތައްޔާރުވަމުން ދަނީ + ހަލުވި ހަރަކާތްތައް ޖުމްލަ MVR ޖުމްލަ USD ކާޑް ސަޕޯޓް @@ -86,6 +87,11 @@ PayMV QR + ތިރި ބާ ޝޯޓްކަޓްތައް + ބަޓަން ހިޔާރު ކުރޭ + ތަން 1 + ތަން 2 + ތަން 3 ތީމް ސިސްޓަމް ލައިޓް @@ -113,6 +119,8 @@ ބަންދު ކެންސަލް + ބޮޓަމް ބާ ލޭބަލް އަބަދުވެސް ދެއްކުން + އެކައުންޓްތައް ލިބެން ހުރި ބެލެންސް diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b8d6c61..72f62ad 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -92,6 +92,7 @@ Pending Finances + Quick Actions MVR Total USD Total Card Support @@ -136,6 +137,12 @@ Drawer Bottom Bar Appearance + Bottom Bar Shortcuts + Always show bottom bar labels + Choose button + Slot 1 + Slot 2 + Slot 3 Privacy & Security Storage Logins