forked from shihaam/thijooree
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
045eb1b1a2
|
|||
|
22806da1b3
|
|||
|
29ac4352ff
|
|||
|
df892ec8d5
|
|||
|
5cba468781
|
@@ -115,11 +115,7 @@ class BasedBankApp : Application() {
|
|||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
// Only apply wallpaper-based dynamic colors in system theme mode.
|
DynamicColors.applyToActivitiesIfAvailable(this)
|
||||||
// Light/dark modes use content-based accent colors applied per-activity via ThemeHelper.
|
|
||||||
DynamicColors.applyToActivitiesIfAvailable(this) { _, _ ->
|
|
||||||
getSharedPreferences("prefs", MODE_PRIVATE).getString("theme", "system") == "system"
|
|
||||||
}
|
|
||||||
|
|
||||||
val theme = getSharedPreferences("prefs", MODE_PRIVATE).getString("theme", "system")
|
val theme = getSharedPreferences("prefs", MODE_PRIVATE).getString("theme", "system")
|
||||||
AppCompatDelegate.setDefaultNightMode(when (theme) {
|
AppCompatDelegate.setDefaultNightMode(when (theme) {
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import kotlinx.coroutines.withContext
|
|||||||
import sh.sar.basedbank.databinding.ActivityLockBinding
|
import sh.sar.basedbank.databinding.ActivityLockBinding
|
||||||
import sh.sar.basedbank.ui.home.HomeActivity
|
import sh.sar.basedbank.ui.home.HomeActivity
|
||||||
import sh.sar.basedbank.util.CredentialStore
|
import sh.sar.basedbank.util.CredentialStore
|
||||||
import sh.sar.basedbank.util.ThemeHelper
|
|
||||||
import sh.sar.basedbank.BasedBankApp
|
import sh.sar.basedbank.BasedBankApp
|
||||||
import javax.crypto.SecretKeyFactory
|
import javax.crypto.SecretKeyFactory
|
||||||
import javax.crypto.spec.PBEKeySpec
|
import javax.crypto.spec.PBEKeySpec
|
||||||
@@ -47,7 +46,6 @@ class LockActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
ThemeHelper.applyAccent(this)
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
binding = ActivityLockBinding.inflate(layoutInflater)
|
binding = ActivityLockBinding.inflate(layoutInflater)
|
||||||
@@ -57,9 +55,6 @@ class LockActivity : AppCompatActivity() {
|
|||||||
isAppearanceLightStatusBars = isLight
|
isAppearanceLightStatusBars = isLight
|
||||||
isAppearanceLightNavigationBars = isLight
|
isAppearanceLightNavigationBars = isLight
|
||||||
}
|
}
|
||||||
val ta = obtainStyledAttributes(intArrayOf(android.R.attr.colorBackground))
|
|
||||||
window.statusBarColor = ta.getColor(0, if (isLight) android.graphics.Color.WHITE else android.graphics.Color.BLACK)
|
|
||||||
ta.recycle()
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, insets ->
|
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, insets ->
|
||||||
val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
view.setPadding(bars.left, bars.top, bars.right, bars.bottom)
|
view.setPadding(bars.left, bars.top, bars.right, bars.bottom)
|
||||||
|
|||||||
@@ -142,6 +142,8 @@ class AccountHistoryFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
adapter.setTransactions(filtered)
|
adapter.setTransactions(filtered)
|
||||||
binding.emptyView.visibility = if (filtered.isEmpty() && !isLoading) View.VISIBLE else View.GONE
|
binding.emptyView.visibility = if (filtered.isEmpty() && !isLoading) View.VISIBLE else View.GONE
|
||||||
|
binding.skeletonContainer.visibility =
|
||||||
|
if (allTransactions.isEmpty() && isLoading) View.VISIBLE else View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetAndReload() {
|
private fun resetAndReload() {
|
||||||
@@ -168,6 +170,9 @@ class AccountHistoryFragment : Fragment() {
|
|||||||
|
|
||||||
if (firstPageDone && allTransactions.isNotEmpty()) {
|
if (firstPageDone && allTransactions.isNotEmpty()) {
|
||||||
adapter.showLoadingFooter = true
|
adapter.showLoadingFooter = true
|
||||||
|
} else if (allTransactions.isEmpty()) {
|
||||||
|
binding.skeletonContainer.visibility = View.VISIBLE
|
||||||
|
binding.emptyView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
val app = requireActivity().application as BasedBankApp
|
val app = requireActivity().application as BasedBankApp
|
||||||
@@ -187,6 +192,7 @@ class AccountHistoryFragment : Fragment() {
|
|||||||
|
|
||||||
isLoading = false
|
isLoading = false
|
||||||
if (_binding == null) return@launch
|
if (_binding == null) return@launch
|
||||||
|
binding.skeletonContainer.visibility = View.GONE
|
||||||
|
|
||||||
if (!firstPageDone) {
|
if (!firstPageDone) {
|
||||||
firstPageDone = true
|
firstPageDone = true
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.widget.addTextChangedListener
|
import androidx.core.widget.addTextChangedListener
|
||||||
@@ -194,10 +195,10 @@ class ContactsFragment : Fragment() {
|
|||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
val success = withContext(Dispatchers.IO) { ContactManager.delete(contact, app) }
|
val success = withContext(Dispatchers.IO) { ContactManager.delete(contact, app) }
|
||||||
if (success) {
|
if (success) {
|
||||||
Toast.makeText(requireContext(), R.string.contact_deleted, Toast.LENGTH_SHORT).show()
|
|
||||||
removeFromViewModel(contact)
|
removeFromViewModel(contact)
|
||||||
|
Snackbar.make(binding.root, R.string.contact_deleted, Snackbar.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(requireContext(), R.string.contact_delete_failed, Toast.LENGTH_SHORT).show()
|
Snackbar.make(binding.root, R.string.contact_delete_failed, Snackbar.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ import sh.sar.basedbank.util.CredentialStore
|
|||||||
import sh.sar.basedbank.util.CardsCache
|
import sh.sar.basedbank.util.CardsCache
|
||||||
import sh.sar.basedbank.util.FinancingCache
|
import sh.sar.basedbank.util.FinancingCache
|
||||||
import sh.sar.basedbank.util.ForeignLimitsCache
|
import sh.sar.basedbank.util.ForeignLimitsCache
|
||||||
import sh.sar.basedbank.util.ThemeHelper
|
|
||||||
|
|
||||||
class HomeActivity : AppCompatActivity() {
|
class HomeActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@@ -107,7 +106,6 @@ class HomeActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
ThemeHelper.applyAccent(this)
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
binding = ActivityHomeBinding.inflate(layoutInflater)
|
binding = ActivityHomeBinding.inflate(layoutInflater)
|
||||||
@@ -120,9 +118,6 @@ class HomeActivity : AppCompatActivity() {
|
|||||||
isAppearanceLightStatusBars = isLight
|
isAppearanceLightStatusBars = isLight
|
||||||
isAppearanceLightNavigationBars = isLight
|
isAppearanceLightNavigationBars = isLight
|
||||||
}
|
}
|
||||||
val ta = obtainStyledAttributes(intArrayOf(android.R.attr.colorBackground))
|
|
||||||
window.statusBarColor = ta.getColor(0, if (isLight) android.graphics.Color.WHITE else android.graphics.Color.BLACK)
|
|
||||||
ta.recycle()
|
|
||||||
// Auth guard: HomeActivity must only be reachable after LockActivity or fresh login.
|
// Auth guard: HomeActivity must only be reachable after LockActivity or fresh login.
|
||||||
// Using loadSecurityHash() (EncryptedSharedPreferences) instead of plain prefs so
|
// Using loadSecurityHash() (EncryptedSharedPreferences) instead of plain prefs so
|
||||||
// a rooted device cannot bypass this by editing security_method in plain prefs.
|
// a rooted device cannot bypass this by editing security_method in plain prefs.
|
||||||
@@ -517,8 +512,9 @@ fun applyNavLabelVisibility() {
|
|||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.toolbar_menu, menu)
|
menuInflater.inflate(R.menu.toolbar_menu, menu)
|
||||||
|
val eyeEnabled = getSharedPreferences("prefs", MODE_PRIVATE).getBoolean("hide_sensitive_info", false)
|
||||||
val eyeItem = menu.findItem(R.id.action_hide_amounts)
|
val eyeItem = menu.findItem(R.id.action_hide_amounts)
|
||||||
eyeItem?.isVisible = true
|
eyeItem?.isVisible = eyeEnabled
|
||||||
val hidden = viewModel.hideAmounts.value ?: false
|
val hidden = viewModel.hideAmounts.value ?: false
|
||||||
eyeItem?.setIcon(if (hidden) R.drawable.ic_visibility_off else R.drawable.ic_visibility)
|
eyeItem?.setIcon(if (hidden) R.drawable.ic_visibility_off else R.drawable.ic_visibility)
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -305,12 +305,7 @@ ViewCompat.setOnApplyWindowInsetsListener(binding.contentLayout) { v, insets ->
|
|||||||
if (statusLabel == null) { tv.visibility = View.GONE; return }
|
if (statusLabel == null) { tv.visibility = View.GONE; return }
|
||||||
tv.visibility = View.VISIBLE
|
tv.visibility = View.VISIBLE
|
||||||
tv.text = statusLabel
|
tv.text = statusLabel
|
||||||
val dp = tv.context.resources.displayMetrics.density
|
tv.setBackgroundResource(R.drawable.card_overlay_pill_bg)
|
||||||
tv.background = GradientDrawable().apply {
|
|
||||||
shape = GradientDrawable.RECTANGLE
|
|
||||||
cornerRadius = 12 * dp
|
|
||||||
setColor(0xCC212121.toInt())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun formatMasked(masked: String): String {
|
fun formatMasked(masked: String): String {
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ package sh.sar.basedbank.ui.home
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.InputType
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -12,7 +10,6 @@ import android.widget.ImageView
|
|||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.ScrollView
|
import android.widget.ScrollView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.appcompat.app.AppCompatDelegate.setApplicationLocales
|
import androidx.appcompat.app.AppCompatDelegate.setApplicationLocales
|
||||||
import androidx.core.os.LocaleListCompat
|
import androidx.core.os.LocaleListCompat
|
||||||
@@ -21,11 +18,8 @@ import androidx.recyclerview.widget.ItemTouchHelper
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
|
||||||
import sh.sar.basedbank.R
|
import sh.sar.basedbank.R
|
||||||
import sh.sar.basedbank.databinding.FragmentSettingsAppearanceBinding
|
import sh.sar.basedbank.databinding.FragmentSettingsAppearanceBinding
|
||||||
import sh.sar.basedbank.util.ThemeHelper
|
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
|
|
||||||
class SettingsAppearanceFragment : Fragment() {
|
class SettingsAppearanceFragment : Fragment() {
|
||||||
@@ -109,45 +103,8 @@ class SettingsAppearanceFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
prefs.edit().putString("theme", key).apply()
|
prefs.edit().putString("theme", key).apply()
|
||||||
AppCompatDelegate.setDefaultNightMode(mode)
|
AppCompatDelegate.setDefaultNightMode(mode)
|
||||||
updateAccentState(key == "system")
|
|
||||||
updatePitchBlackState(key == "dark")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pitch black
|
|
||||||
binding.switchPitchBlack.isChecked = prefs.getBoolean("pitch_black", false)
|
|
||||||
binding.switchPitchBlack.setOnCheckedChangeListener { _, checked ->
|
|
||||||
prefs.edit().putBoolean("pitch_black", checked).apply()
|
|
||||||
requireActivity().recreate()
|
|
||||||
}
|
|
||||||
val isDark = prefs.getString("theme", "system") == "dark"
|
|
||||||
updatePitchBlackState(isDark)
|
|
||||||
|
|
||||||
// Accent color
|
|
||||||
val savedPreset = prefs.getString("accent_preset", ThemeHelper.PRESET_BLUE)
|
|
||||||
binding.accentToggle.check(when (savedPreset) {
|
|
||||||
ThemeHelper.PRESET_RED -> R.id.btnAccentOrange
|
|
||||||
ThemeHelper.PRESET_GREEN -> R.id.btnAccentGreen
|
|
||||||
ThemeHelper.PRESET_CUSTOM -> R.id.btnAccentCustom
|
|
||||||
else -> R.id.btnAccentBlue
|
|
||||||
})
|
|
||||||
binding.accentToggle.addOnButtonCheckedListener { _, checkedId, isChecked ->
|
|
||||||
if (!isChecked) return@addOnButtonCheckedListener
|
|
||||||
val preset = when (checkedId) {
|
|
||||||
R.id.btnAccentOrange -> ThemeHelper.PRESET_RED
|
|
||||||
R.id.btnAccentGreen -> ThemeHelper.PRESET_GREEN
|
|
||||||
R.id.btnAccentCustom -> ThemeHelper.PRESET_CUSTOM
|
|
||||||
else -> ThemeHelper.PRESET_BLUE
|
|
||||||
}
|
|
||||||
if (preset == ThemeHelper.PRESET_CUSTOM) {
|
|
||||||
showCustomColorPicker()
|
|
||||||
} else {
|
|
||||||
prefs.edit().putString("accent_preset", preset).apply()
|
|
||||||
requireActivity().recreate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val isSystem = prefs.getString("theme", "system") == "system"
|
|
||||||
updateAccentState(isSystem)
|
|
||||||
|
|
||||||
// Language
|
// Language
|
||||||
val currentLocales = AppCompatDelegate.getApplicationLocales()
|
val currentLocales = AppCompatDelegate.getApplicationLocales()
|
||||||
val currentLang = if (currentLocales.isEmpty) "en" else currentLocales[0]?.language ?: "en"
|
val currentLang = if (currentLocales.isEmpty) "en" else currentLocales[0]?.language ?: "en"
|
||||||
@@ -199,68 +156,6 @@ class SettingsAppearanceFragment : Fragment() {
|
|||||||
slotAdapter.notifyDataSetChanged()
|
slotAdapter.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePitchBlackState(isDark: Boolean) {
|
|
||||||
binding.rowPitchBlack.alpha = if (isDark) 1f else 0.38f
|
|
||||||
binding.switchPitchBlack.isEnabled = isDark
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateAccentState(isSystem: Boolean) {
|
|
||||||
binding.sectionAccentColor.alpha = if (isSystem) 0.38f else 1f
|
|
||||||
for (i in 0 until binding.accentToggle.childCount) {
|
|
||||||
binding.accentToggle.getChildAt(i)?.isEnabled = !isSystem
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showCustomColorPicker() {
|
|
||||||
val ctx = requireContext()
|
|
||||||
val currentHex = prefs.getString("accent_custom_color", "") ?: ""
|
|
||||||
val inputLayout = TextInputLayout(ctx).apply {
|
|
||||||
hint = getString(R.string.accent_custom_hint)
|
|
||||||
val pad = (16 * resources.displayMetrics.density).toInt()
|
|
||||||
setPadding(pad, pad / 2, pad, 0)
|
|
||||||
}
|
|
||||||
val input = TextInputEditText(ctx).apply {
|
|
||||||
setText(currentHex)
|
|
||||||
inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
|
|
||||||
setSingleLine(true)
|
|
||||||
}
|
|
||||||
inputLayout.addView(input)
|
|
||||||
|
|
||||||
val dialog = MaterialAlertDialogBuilder(ctx)
|
|
||||||
.setTitle(R.string.accent_custom_pick)
|
|
||||||
.setView(inputLayout)
|
|
||||||
.setPositiveButton(android.R.string.ok, null)
|
|
||||||
.setNegativeButton(R.string.cancel) { _, _ -> revertAccentToggle() }
|
|
||||||
.setOnCancelListener { revertAccentToggle() }
|
|
||||||
.show()
|
|
||||||
|
|
||||||
dialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
|
||||||
val raw = input.text.toString().trim()
|
|
||||||
val hex = if (raw.startsWith("#")) raw else "#$raw"
|
|
||||||
try {
|
|
||||||
Color.parseColor(hex)
|
|
||||||
prefs.edit()
|
|
||||||
.putString("accent_preset", ThemeHelper.PRESET_CUSTOM)
|
|
||||||
.putString("accent_custom_color", hex)
|
|
||||||
.apply()
|
|
||||||
dialog.dismiss()
|
|
||||||
requireActivity().recreate()
|
|
||||||
} catch (_: Exception) {
|
|
||||||
Toast.makeText(ctx, R.string.accent_invalid_color, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun revertAccentToggle() {
|
|
||||||
val saved = prefs.getString("accent_preset", ThemeHelper.PRESET_BLUE)
|
|
||||||
binding.accentToggle.check(when (saved) {
|
|
||||||
ThemeHelper.PRESET_RED -> R.id.btnAccentOrange
|
|
||||||
ThemeHelper.PRESET_GREEN -> R.id.btnAccentGreen
|
|
||||||
ThemeHelper.PRESET_CUSTOM -> R.id.btnAccentCustom
|
|
||||||
else -> R.id.btnAccentBlue
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showItemPicker(items: MutableList<Int>, slotIndex: Int, adapter: NavItemAdapter) {
|
private fun showItemPicker(items: MutableList<Int>, slotIndex: Int, adapter: NavItemAdapter) {
|
||||||
val isBottom = prefs.getBoolean("bottom_nav", false)
|
val isBottom = prefs.getBoolean("bottom_nav", false)
|
||||||
if (items === slots && !isBottom) return
|
if (items === slots && !isBottom) return
|
||||||
@@ -273,7 +168,6 @@ class SettingsAppearanceFragment : Fragment() {
|
|||||||
LayoutInflater.from(ctx).inflate(R.layout.item_more_nav, listLayout, false).also { row ->
|
LayoutInflater.from(ctx).inflate(R.layout.item_more_nav, listLayout, false).also { row ->
|
||||||
row.findViewById<ImageView>(R.id.ivIcon).setImageResource(item.iconRes)
|
row.findViewById<ImageView>(R.id.ivIcon).setImageResource(item.iconRes)
|
||||||
row.findViewById<TextView>(R.id.tvLabel).setText(item.titleRes)
|
row.findViewById<TextView>(R.id.tvLabel).setText(item.titleRes)
|
||||||
row.findViewById<TextView>(R.id.tvDescription).visibility = View.GONE
|
|
||||||
listLayout.addView(row)
|
listLayout.addView(row)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,17 @@ class SettingsSecurityFragment : Fragment() {
|
|||||||
(activity as? HomeActivity)?.resetAutolockTimer()
|
(activity as? HomeActivity)?.resetAutolockTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hide sensitive information (enables/disables the eye icon in toolbar)
|
||||||
|
val viewModel = (requireActivity() as HomeActivity).let {
|
||||||
|
androidx.lifecycle.ViewModelProvider(it)[HomeViewModel::class.java]
|
||||||
|
}
|
||||||
|
binding.switchHideAmounts.isChecked = prefs.getBoolean("hide_sensitive_info", false)
|
||||||
|
binding.switchHideAmounts.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
prefs.edit().putBoolean("hide_sensitive_info", isChecked).apply()
|
||||||
|
if (!isChecked) viewModel.hideAmounts.value = false
|
||||||
|
requireActivity().invalidateOptionsMenu()
|
||||||
|
}
|
||||||
|
|
||||||
// Block screenshots
|
// Block screenshots
|
||||||
val blockScreenshots = prefs.getBoolean("block_screenshots", true)
|
val blockScreenshots = prefs.getBoolean("block_screenshots", true)
|
||||||
binding.switchBlockScreenshots.isChecked = blockScreenshots
|
binding.switchBlockScreenshots.isChecked = blockScreenshots
|
||||||
|
|||||||
@@ -181,6 +181,9 @@ class TransferHistoryFragment : Fragment() {
|
|||||||
|
|
||||||
if (firstBatchDone && allTransactions.isNotEmpty()) {
|
if (firstBatchDone && allTransactions.isNotEmpty()) {
|
||||||
adapter.showLoadingFooter = true
|
adapter.showLoadingFooter = true
|
||||||
|
} else if (allTransactions.isEmpty()) {
|
||||||
|
binding.skeletonContainer.visibility = View.VISIBLE
|
||||||
|
binding.emptyView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
val app = requireActivity().application as BasedBankApp
|
val app = requireActivity().application as BasedBankApp
|
||||||
@@ -286,6 +289,7 @@ class TransferHistoryFragment : Fragment() {
|
|||||||
|
|
||||||
isLoading = false
|
isLoading = false
|
||||||
if (_binding == null) return@launch
|
if (_binding == null) return@launch
|
||||||
|
binding.skeletonContainer.visibility = View.GONE
|
||||||
|
|
||||||
val raw = bannerMsg.get()
|
val raw = bannerMsg.get()
|
||||||
when {
|
when {
|
||||||
@@ -329,6 +333,8 @@ class TransferHistoryFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
adapter.setTransactions(filtered)
|
adapter.setTransactions(filtered)
|
||||||
binding.emptyView.visibility = if (filtered.isEmpty() && !isLoading) View.VISIBLE else View.GONE
|
binding.emptyView.visibility = if (filtered.isEmpty() && !isLoading) View.VISIBLE else View.GONE
|
||||||
|
binding.skeletonContainer.visibility =
|
||||||
|
if (allTransactions.isEmpty() && isLoading) View.VISIBLE else View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadContactImage(name: String) {
|
private fun loadContactImage(name: String) {
|
||||||
|
|||||||
@@ -9,14 +9,12 @@ import sh.sar.basedbank.BasedBankApp
|
|||||||
import sh.sar.basedbank.LockActivity
|
import sh.sar.basedbank.LockActivity
|
||||||
import sh.sar.basedbank.databinding.ActivityLoginBinding
|
import sh.sar.basedbank.databinding.ActivityLoginBinding
|
||||||
import sh.sar.basedbank.util.CredentialStore
|
import sh.sar.basedbank.util.CredentialStore
|
||||||
import sh.sar.basedbank.util.ThemeHelper
|
|
||||||
|
|
||||||
class LoginActivity : AppCompatActivity() {
|
class LoginActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var binding: ActivityLoginBinding
|
private lateinit var binding: ActivityLoginBinding
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
ThemeHelper.applyAccent(this)
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
// If security is configured and the user hasn't unlocked this session,
|
// If security is configured and the user hasn't unlocked this session,
|
||||||
@@ -36,8 +34,5 @@ class LoginActivity : AppCompatActivity() {
|
|||||||
isAppearanceLightStatusBars = isLight
|
isAppearanceLightStatusBars = isLight
|
||||||
isAppearanceLightNavigationBars = isLight
|
isAppearanceLightNavigationBars = isLight
|
||||||
}
|
}
|
||||||
val ta = obtainStyledAttributes(intArrayOf(android.R.attr.colorBackground))
|
|
||||||
window.statusBarColor = ta.getColor(0, if (isLight) android.graphics.Color.WHITE else android.graphics.Color.BLACK)
|
|
||||||
ta.recycle()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import sh.sar.basedbank.R
|
|||||||
import sh.sar.basedbank.databinding.ActivityOnboardingBinding
|
import sh.sar.basedbank.databinding.ActivityOnboardingBinding
|
||||||
import sh.sar.basedbank.ui.login.LoginActivity
|
import sh.sar.basedbank.ui.login.LoginActivity
|
||||||
import sh.sar.basedbank.util.CredentialStore
|
import sh.sar.basedbank.util.CredentialStore
|
||||||
import sh.sar.basedbank.util.ThemeHelper
|
|
||||||
|
|
||||||
class OnboardingActivity : AppCompatActivity(), SecuritySetupFragment.Callback {
|
class OnboardingActivity : AppCompatActivity(), SecuritySetupFragment.Callback {
|
||||||
|
|
||||||
@@ -28,7 +27,6 @@ class OnboardingActivity : AppCompatActivity(), SecuritySetupFragment.Callback {
|
|||||||
private var countDownTimer: CountDownTimer? = null
|
private var countDownTimer: CountDownTimer? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
ThemeHelper.applyAccent(this)
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
// If security is already configured, onboarding is complete. Redirect to lock screen
|
// If security is already configured, onboarding is complete. Redirect to lock screen
|
||||||
@@ -47,9 +45,6 @@ class OnboardingActivity : AppCompatActivity(), SecuritySetupFragment.Callback {
|
|||||||
isAppearanceLightStatusBars = isLight
|
isAppearanceLightStatusBars = isLight
|
||||||
isAppearanceLightNavigationBars = isLight
|
isAppearanceLightNavigationBars = isLight
|
||||||
}
|
}
|
||||||
val ta = obtainStyledAttributes(intArrayOf(android.R.attr.colorBackground))
|
|
||||||
window.statusBarColor = ta.getColor(0, if (isLight) android.graphics.Color.WHITE else android.graphics.Color.BLACK)
|
|
||||||
ta.recycle()
|
|
||||||
prefs = getSharedPreferences("prefs", MODE_PRIVATE)
|
prefs = getSharedPreferences("prefs", MODE_PRIVATE)
|
||||||
val originalBottomPadding = binding.bottomBar.paddingBottom
|
val originalBottomPadding = binding.bottomBar.paddingBottom
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(binding.bottomBar) { view, insets ->
|
ViewCompat.setOnApplyWindowInsetsListener(binding.bottomBar) { view, insets ->
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
package sh.sar.basedbank.util
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Build
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import com.google.android.material.color.DynamicColors
|
|
||||||
import com.google.android.material.color.DynamicColorsOptions
|
|
||||||
import sh.sar.basedbank.R
|
|
||||||
|
|
||||||
object ThemeHelper {
|
|
||||||
|
|
||||||
const val PRESET_BLUE = "blue"
|
|
||||||
const val PRESET_RED = "red"
|
|
||||||
const val PRESET_GREEN = "green"
|
|
||||||
const val PRESET_CUSTOM = "custom"
|
|
||||||
|
|
||||||
fun isSystemTheme(context: Context): Boolean =
|
|
||||||
context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
|
|
||||||
.getString("theme", "system") == "system"
|
|
||||||
|
|
||||||
fun getAccentPreset(context: Context): String =
|
|
||||||
context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
|
|
||||||
.getString("accent_preset", PRESET_BLUE) ?: PRESET_BLUE
|
|
||||||
|
|
||||||
fun getCustomColor(context: Context): Int? {
|
|
||||||
val hex = context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
|
|
||||||
.getString("accent_custom_color", null) ?: return null
|
|
||||||
return try { Color.parseColor(hex) } catch (_: Exception) { null }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun presetSeedColor(context: Context, preset: String): Int = when (preset) {
|
|
||||||
PRESET_RED -> Color.parseColor("#D32F2F")
|
|
||||||
PRESET_GREEN -> Color.parseColor("#4CAF50")
|
|
||||||
PRESET_CUSTOM -> getCustomColor(context) ?: Color.parseColor("#3F65AD")
|
|
||||||
else -> Color.parseColor("#3F65AD")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isPitchBlackEnabled(context: Context): Boolean =
|
|
||||||
context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
|
|
||||||
.getBoolean("pitch_black", false)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply the user-chosen accent theme to the given activity.
|
|
||||||
* Must be called BEFORE super.onCreate() so window-level attributes
|
|
||||||
* (status bar color, etc.) are resolved from the correct overlay.
|
|
||||||
* Has no effect when the theme is set to "system" (dynamic colors are
|
|
||||||
* handled by BasedBankApp via DynamicColors.applyToActivitiesIfAvailable).
|
|
||||||
*/
|
|
||||||
fun applyAccent(activity: AppCompatActivity) {
|
|
||||||
if (isSystemTheme(activity)) return
|
|
||||||
val preset = getAccentPreset(activity)
|
|
||||||
val seed = presetSeedColor(activity, preset)
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
||||||
val bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
|
|
||||||
bitmap.setPixel(0, 0, seed)
|
|
||||||
DynamicColors.applyToActivityIfAvailable(
|
|
||||||
activity,
|
|
||||||
DynamicColorsOptions.Builder().setContentBasedSource(bitmap).build()
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// API < 31: apply a simple style overlay (partial palette, but functional)
|
|
||||||
val styleRes = when (preset) {
|
|
||||||
PRESET_RED -> R.style.ThemeOverlay_Accent_Orange
|
|
||||||
PRESET_GREEN -> R.style.ThemeOverlay_Accent_Green
|
|
||||||
else -> R.style.ThemeOverlay_Accent_Blue
|
|
||||||
}
|
|
||||||
activity.theme.applyStyle(styleRes, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
val prefs = activity.getSharedPreferences("prefs", Context.MODE_PRIVATE)
|
|
||||||
val isDark = prefs.getString("theme", "system") == "dark"
|
|
||||||
if (isDark && prefs.getBoolean("pitch_black", false)) {
|
|
||||||
activity.theme.applyStyle(R.style.ThemeOverlay_PitchBlack, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Translucent dark pill used as a status overlay on card-visual surfaces
|
||||||
|
(item_card_dashboard / _stack / _wallet / _settings_entry). Theme-independent
|
||||||
|
by design: it sits on top of card artwork, not the surface color. -->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="12dp" />
|
||||||
|
<solid android:color="#CC212121" />
|
||||||
|
</shape>
|
||||||
@@ -4,6 +4,6 @@
|
|||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:fillColor="?attr/colorOnSurfaceVariant"
|
android:fillColor="?attr/colorOnSurface"
|
||||||
android:pathData="M9.5,6.5v3h-3v-3H9.5zM11,5L5,5v5.5h6L11,5zM9.5,14.5v3h-3v-3H9.5zM11,13L5,13v5.5h6L11,13zM17.5,6.5v3h-3v-3H17.5zM19,5h-6v5.5h6L19,5zM13,13h1.5v1.5L13,14.5zM14.5,14.5L16,14.5L16,16h-1.5zM16,13h1.5v1.5L16,14.5zM13,16h1.5v1.5L13,17.5zM14.5,17.5L16,17.5L16,19h-1.5zM16,16h1.5v1.5L16,17.5zM17.5,14.5L19,14.5L19,16h-1.5zM17.5,17.5L19,17.5L19,19h-1.5z"/>
|
android:pathData="M9.5,6.5v3h-3v-3H9.5zM11,5L5,5v5.5h6L11,5zM9.5,14.5v3h-3v-3H9.5zM11,13L5,13v5.5h6L11,13zM17.5,6.5v3h-3v-3H17.5zM19,5h-6v5.5h6L19,5zM13,13h1.5v1.5L13,14.5zM14.5,14.5L16,14.5L16,16h-1.5zM16,13h1.5v1.5L16,14.5zM13,16h1.5v1.5L13,17.5zM14.5,17.5L16,17.5L16,19h-1.5zM16,16h1.5v1.5L16,17.5zM17.5,14.5L19,14.5L19,16h-1.5zM17.5,17.5L19,17.5L19,19h-1.5z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@@ -44,8 +44,8 @@
|
|||||||
android:id="@+id/connectivityBanner"
|
android:id="@+id/connectivityBanner"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="#C62828"
|
android:background="?attr/colorErrorContainer"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="?attr/colorOnErrorContainer"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingTop="6dp"
|
android:paddingTop="6dp"
|
||||||
android:paddingBottom="6dp"
|
android:paddingBottom="6dp"
|
||||||
|
|||||||
@@ -48,12 +48,28 @@
|
|||||||
android:paddingBottom="16dp"
|
android:paddingBottom="16dp"
|
||||||
android:clipToPadding="false" />
|
android:clipToPadding="false" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/skeletonContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/emptyView"
|
android:id="@+id/emptyView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="No transactions found"
|
android:text="@string/transactions_empty"
|
||||||
android:textAppearance="?attr/textAppearanceBodyMedium"
|
android:textAppearance="?attr/textAppearanceBodyMedium"
|
||||||
android:textColor="?attr/colorOnSurfaceVariant"
|
android:textColor="?attr/colorOnSurfaceVariant"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="No recent transfers"
|
android:text="@string/activities_empty"
|
||||||
android:textAppearance="?attr/textAppearanceBodyMedium"
|
android:textAppearance="?attr/textAppearanceBodyMedium"
|
||||||
android:textColor="?attr/colorOnSurfaceVariant"
|
android:textColor="?attr/colorOnSurfaceVariant"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="@dimen/card_radius_lg"
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:strokeColor="?attr/colorOutline">
|
app:strokeColor="?attr/colorOutline">
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="@dimen/card_radius_lg"
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:strokeColor="?attr/colorOutline">
|
app:strokeColor="?attr/colorOutline">
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@
|
|||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="@dimen/card_radius_lg"
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:strokeColor="?attr/colorOutline">
|
app:strokeColor="?attr/colorOutline">
|
||||||
|
|
||||||
|
|||||||
@@ -117,8 +117,8 @@
|
|||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
app:cardBackgroundColor="?attr/colorSecondaryContainer"
|
app:cardBackgroundColor="?attr/colorSecondaryContainer"
|
||||||
app:cardCornerRadius="12dp"
|
app:cardCornerRadius="@dimen/card_radius_md"
|
||||||
app:cardElevation="0dp">
|
app:cardElevation="@dimen/card_elevation_flat">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="16dp">
|
android:padding="@dimen/screen_margin">
|
||||||
|
|
||||||
<!-- Balance cards row -->
|
<!-- Balance cards row -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -34,8 +34,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
app:cardElevation="1dp"
|
app:cardElevation="@dimen/card_elevation_raised"
|
||||||
app:cardCornerRadius="12dp">
|
app:cardCornerRadius="@dimen/card_radius_md">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -56,7 +56,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="MVR —"
|
android:text="MVR —"
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium" />
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -67,8 +68,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
app:cardElevation="1dp"
|
app:cardElevation="@dimen/card_elevation_raised"
|
||||||
app:cardCornerRadius="12dp">
|
app:cardCornerRadius="@dimen/card_radius_md">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -89,7 +90,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="USD —"
|
android:text="USD —"
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium" />
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -112,8 +114,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
app:cardElevation="1dp"
|
app:cardElevation="@dimen/card_elevation_raised"
|
||||||
app:cardCornerRadius="12dp">
|
app:cardCornerRadius="@dimen/card_radius_md">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -134,7 +136,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="MVR —"
|
android:text="MVR —"
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium" />
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -146,8 +149,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
app:cardElevation="1dp"
|
app:cardElevation="@dimen/card_elevation_raised"
|
||||||
app:cardCornerRadius="12dp">
|
app:cardCornerRadius="@dimen/card_radius_md">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -168,7 +171,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="USD —"
|
android:text="USD —"
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium" />
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -191,8 +195,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
app:cardElevation="1dp"
|
app:cardElevation="@dimen/card_elevation_raised"
|
||||||
app:cardCornerRadius="12dp"
|
app:cardCornerRadius="@dimen/card_radius_md"
|
||||||
app:cardBackgroundColor="?attr/colorErrorContainer"
|
app:cardBackgroundColor="?attr/colorErrorContainer"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
@@ -216,7 +220,8 @@
|
|||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="MVR —"
|
android:text="MVR —"
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium"
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
android:textColor="?attr/colorOnErrorContainer" />
|
android:textColor="?attr/colorOnErrorContainer"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvBlockedSecondary"
|
android:id="@+id/tvBlockedSecondary"
|
||||||
@@ -225,6 +230,7 @@
|
|||||||
android:layout_marginTop="2dp"
|
android:layout_marginTop="2dp"
|
||||||
android:textAppearance="?attr/textAppearanceLabelSmall"
|
android:textAppearance="?attr/textAppearanceLabelSmall"
|
||||||
android:textColor="?attr/colorOnErrorContainer"
|
android:textColor="?attr/colorOnErrorContainer"
|
||||||
|
android:fontFeatureSettings="tnum"
|
||||||
android:alpha="0.75"
|
android:alpha="0.75"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
@@ -238,8 +244,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
app:cardElevation="1dp"
|
app:cardElevation="@dimen/card_elevation_raised"
|
||||||
app:cardCornerRadius="12dp"
|
app:cardCornerRadius="@dimen/card_radius_md"
|
||||||
app:cardBackgroundColor="?attr/colorErrorContainer"
|
app:cardBackgroundColor="?attr/colorErrorContainer"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
@@ -265,7 +271,8 @@
|
|||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="MVR —"
|
android:text="MVR —"
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium"
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
android:textColor="?attr/colorOnErrorContainer" />
|
android:textColor="?attr/colorOnErrorContainer"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -279,8 +286,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
app:cardElevation="1dp"
|
app:cardElevation="@dimen/card_elevation_raised"
|
||||||
app:cardCornerRadius="12dp"
|
app:cardCornerRadius="@dimen/card_radius_md"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true">
|
android:focusable="true">
|
||||||
|
|
||||||
@@ -303,7 +310,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:text="MVR —"
|
android:text="MVR —"
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium" />
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -325,6 +333,14 @@
|
|||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/nav_pay_with_card"
|
||||||
|
android:textAppearance="?attr/textAppearanceLabelMedium"
|
||||||
|
android:textColor="?attr/colorOnSurfaceVariant"
|
||||||
|
android:layout_marginBottom="8dp"/>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rvCards"
|
android:id="@+id/rvCards"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -350,6 +366,14 @@
|
|||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingBottom="16dp">
|
android:paddingBottom="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/dashboard_quick_actions"
|
||||||
|
android:textAppearance="?attr/textAppearanceLabelMedium"
|
||||||
|
android:textColor="?attr/colorOnSurfaceVariant"
|
||||||
|
android:layout_marginBottom="8dp" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="12dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="@dimen/card_radius_lg"
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:strokeColor="?attr/colorOutline">
|
app:strokeColor="?attr/colorOutline">
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="@dimen/card_radius_lg"
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:strokeColor="?attr/colorOutline">
|
app:strokeColor="?attr/colorOutline">
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|||||||
@@ -156,87 +156,6 @@
|
|||||||
|
|
||||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||||
|
|
||||||
<!-- Pitch black — enabled only in explicit dark mode -->
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/rowPitchBlack"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/settings_pitch_black"
|
|
||||||
android:textAppearance="?attr/textAppearanceBodyLarge" />
|
|
||||||
|
|
||||||
<com.google.android.material.materialswitch.MaterialSwitch
|
|
||||||
android:id="@+id/switchPitchBlack"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!-- Accent color — always shown, disabled/grayed in system theme mode -->
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/sectionAccentColor"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_marginTop="24dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/settings_accent_color"
|
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium"
|
|
||||||
android:layout_marginBottom="12dp" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
|
||||||
android:id="@+id/accentToggle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:singleSelection="true"
|
|
||||||
app:selectionRequired="true">
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/btnAccentBlue"
|
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/accent_blue" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/btnAccentOrange"
|
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/accent_orange" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/btnAccentGreen"
|
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/accent_green" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/btnAccentCustom"
|
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/accent_custom" />
|
|
||||||
|
|
||||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -194,6 +194,44 @@
|
|||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
android:layout_marginBottom="8dp" />
|
android:layout_marginBottom="8dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/rowHideAmounts"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginBottom="4dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/settings_hide_amounts"
|
||||||
|
android:textAppearance="?attr/textAppearanceBodyLarge"
|
||||||
|
android:textColor="?attr/colorOnSurface" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/settings_hide_amounts_desc"
|
||||||
|
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||||
|
android:textColor="?attr/colorOnSurfaceVariant" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
|
android:id="@+id/switchHideAmounts"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/rowBlockScreenshots"
|
android:id="@+id/rowBlockScreenshots"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -49,12 +49,28 @@
|
|||||||
android:paddingBottom="16dp"
|
android:paddingBottom="16dp"
|
||||||
android:clipToPadding="false" />
|
android:clipToPadding="false" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/skeletonContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
<include layout="@layout/item_skeleton_transaction" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/emptyView"
|
android:id="@+id/emptyView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="No transactions found"
|
android:text="@string/transactions_empty"
|
||||||
android:textAppearance="?attr/textAppearanceBodyMedium"
|
android:textAppearance="?attr/textAppearanceBodyMedium"
|
||||||
android:textColor="?attr/colorOnSurfaceVariant"
|
android:textColor="?attr/colorOnSurfaceVariant"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="@dimen/list_item_padding_h"
|
||||||
android:paddingVertical="14dp"
|
android:paddingVertical="@dimen/list_item_padding_v"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:foreground="?attr/selectableItemBackground">
|
android:foreground="?attr/selectableItemBackground">
|
||||||
|
|
||||||
@@ -70,7 +70,8 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?attr/textAppearanceTitleSmall"
|
android:textAppearance="?attr/textAppearanceTitleSmall"
|
||||||
android:textColor="?attr/colorOnSurface" />
|
android:textColor="?attr/colorOnSurface"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvBlocked"
|
android:id="@+id/tvBlocked"
|
||||||
@@ -79,6 +80,7 @@
|
|||||||
android:layout_marginTop="2dp"
|
android:layout_marginTop="2dp"
|
||||||
android:textAppearance="?attr/textAppearanceLabelSmall"
|
android:textAppearance="?attr/textAppearanceLabelSmall"
|
||||||
android:textColor="?attr/colorError"
|
android:textColor="?attr/colorError"
|
||||||
|
android:fontFeatureSettings="tnum"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
app:shapeAppearanceOverlay="@style/ShapeAppearance.Circle"
|
app:shapeAppearanceOverlay="@style/ShapeAppearance.Circle"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
||||||
|
|
||||||
@@ -49,7 +50,8 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||||
android:textColor="?attr/colorOnSurface" />
|
android:textColor="?attr/colorOnSurface"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="@dimen/card_radius_lg"
|
||||||
app:cardElevation="0dp"
|
app:cardElevation="@dimen/card_elevation_flat"
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:strokeColor="?attr/colorOutlineVariant">
|
app:strokeColor="?attr/colorOutlineVariant">
|
||||||
|
|
||||||
@@ -114,7 +114,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium"
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
android:textColor="?attr/colorOnSurface"
|
android:textColor="?attr/colorOnSurface"
|
||||||
android:layout_marginTop="2dp" />
|
android:layout_marginTop="2dp"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -137,7 +138,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium"
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
android:textColor="?attr/colorOnSurface"
|
android:textColor="?attr/colorOnSurface"
|
||||||
android:layout_marginTop="2dp" />
|
android:layout_marginTop="2dp"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -162,7 +164,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium"
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
android:textColor="?attr/colorError"
|
android:textColor="?attr/colorError"
|
||||||
android:layout_marginTop="2dp" />
|
android:layout_marginTop="2dp"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,10 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="12dp"
|
||||||
app:cardCornerRadius="16dp"
|
android:clickable="true"
|
||||||
app:cardElevation="0dp"
|
android:focusable="true"
|
||||||
|
app:cardCornerRadius="@dimen/card_radius_lg"
|
||||||
|
app:cardElevation="@dimen/card_elevation_flat"
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:strokeColor="?attr/colorOutlineVariant">
|
app:strokeColor="?attr/colorOutlineVariant">
|
||||||
|
|
||||||
@@ -51,11 +53,7 @@
|
|||||||
android:id="@+id/tvLoanStatus"
|
android:id="@+id/tvLoanStatus"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingHorizontal="10dp"
|
style="@style/Widget.App.StatusChip" />
|
||||||
android:paddingVertical="4dp"
|
|
||||||
android:background="@drawable/chip_background"
|
|
||||||
android:textAppearance="?attr/textAppearanceLabelSmall"
|
|
||||||
android:textColor="?attr/colorOnSecondaryContainer" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="@dimen/list_item_padding_h"
|
||||||
android:paddingVertical="14dp"
|
android:paddingVertical="@dimen/list_item_padding_v"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:foreground="?attr/selectableItemBackground">
|
android:foreground="?attr/selectableItemBackground">
|
||||||
|
|
||||||
@@ -83,7 +83,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?attr/textAppearanceTitleSmall"
|
android:textAppearance="?attr/textAppearanceTitleSmall"
|
||||||
android:textColor="?attr/colorOnSurface"
|
android:textColor="?attr/colorOnSurface"
|
||||||
android:layout_marginTop="6dp" />
|
android:layout_marginTop="6dp"
|
||||||
|
android:fontFeatureSettings="tnum" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/btnTransfer"
|
android:id="@+id/btnTransfer"
|
||||||
|
|||||||
@@ -5,8 +5,10 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="12dp"
|
||||||
app:cardCornerRadius="16dp"
|
android:clickable="true"
|
||||||
app:cardElevation="0dp"
|
android:focusable="true"
|
||||||
|
app:cardCornerRadius="@dimen/card_radius_lg"
|
||||||
|
app:cardElevation="@dimen/card_elevation_flat"
|
||||||
app:strokeWidth="1dp"
|
app:strokeWidth="1dp"
|
||||||
app:strokeColor="?attr/colorOutlineVariant">
|
app:strokeColor="?attr/colorOutlineVariant">
|
||||||
|
|
||||||
@@ -51,11 +53,7 @@
|
|||||||
android:id="@+id/tvStatus"
|
android:id="@+id/tvStatus"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingHorizontal="10dp"
|
style="@style/Widget.App.StatusChip" />
|
||||||
android:paddingVertical="4dp"
|
|
||||||
android:background="@drawable/chip_background"
|
|
||||||
android:textAppearance="?attr/textAppearanceLabelSmall"
|
|
||||||
android:textColor="?attr/colorOnSecondaryContainer" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,10 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
app:cardElevation="1dp"
|
android:clickable="true"
|
||||||
app:cardCornerRadius="12dp">
|
android:focusable="true"
|
||||||
|
app:cardElevation="@dimen/card_elevation_raised"
|
||||||
|
app:cardCornerRadius="@dimen/card_radius_md">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -5,15 +5,16 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="@dimen/list_item_padding_h"
|
||||||
android:paddingVertical="14dp"
|
android:paddingVertical="@dimen/list_item_padding_v"
|
||||||
android:background="?attr/selectableItemBackground">
|
android:background="?attr/selectableItemBackground">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/ivIcon"
|
android:id="@+id/ivIcon"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_marginEnd="16dp" />
|
android:layout_marginEnd="16dp"
|
||||||
|
android:importantForAccessibility="no" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
android:id="@+id/ivNavIcon"
|
android:id="@+id/ivNavIcon"
|
||||||
android:layout_width="28dp"
|
android:layout_width="28dp"
|
||||||
android:layout_height="28dp"
|
android:layout_height="28dp"
|
||||||
android:layout_marginBottom="6dp" />
|
android:layout_marginBottom="6dp"
|
||||||
|
android:importantForAccessibility="no" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvNavLabel"
|
android:id="@+id/tvNavLabel"
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="12dp"
|
||||||
app:cardCornerRadius="16dp"
|
app:cardCornerRadius="@dimen/card_radius_lg"
|
||||||
app:cardElevation="2dp">
|
app:cardElevation="@dimen/card_elevation_raised">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
android:layout_width="44dp"
|
android:layout_width="44dp"
|
||||||
android:layout_height="44dp"
|
android:layout_height="44dp"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
app:shapeAppearanceOverlay="@style/ShapeAppearance.Circle" />
|
app:shapeAppearanceOverlay="@style/ShapeAppearance.Circle" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -53,6 +54,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?attr/textAppearanceTitleMedium"
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
android:textColor="?attr/colorOnSurface"
|
android:textColor="?attr/colorOnSurface"
|
||||||
|
android:fontFeatureSettings="tnum"
|
||||||
android:paddingHorizontal="8dp"
|
android:paddingHorizontal="8dp"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,6 @@
|
|||||||
android:id="@+id/tvProfileType"
|
android:id="@+id/tvProfileType"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingHorizontal="10dp"
|
style="@style/Widget.App.StatusChip" />
|
||||||
android:paddingVertical="4dp"
|
|
||||||
android:background="@drawable/chip_background"
|
|
||||||
android:textAppearance="?attr/textAppearanceLabelSmall"
|
|
||||||
android:textColor="?attr/colorOnSecondaryContainer" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -86,6 +86,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?attr/textAppearanceTitleSmall"
|
android:textAppearance="?attr/textAppearanceTitleSmall"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
android:fontFeatureSettings="tnum"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/fvAvatar"
|
app:layout_constraintTop_toTopOf="@id/fvAvatar"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/fvAvatar" />
|
app:layout_constraintBottom_toBottomOf="@id/fvAvatar" />
|
||||||
|
|||||||
@@ -65,8 +65,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="12dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:cardCornerRadius="12dp"
|
app:cardCornerRadius="@dimen/card_radius_md"
|
||||||
app:cardElevation="2dp">
|
app:cardElevation="@dimen/card_elevation_raised">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -5,4 +5,36 @@
|
|||||||
<dimen name="nav_header_vertical_spacing">8dp</dimen>
|
<dimen name="nav_header_vertical_spacing">8dp</dimen>
|
||||||
<dimen name="nav_header_height">176dp</dimen>
|
<dimen name="nav_header_height">176dp</dimen>
|
||||||
<dimen name="fab_margin">16dp</dimen>
|
<dimen name="fab_margin">16dp</dimen>
|
||||||
</resources>
|
|
||||||
|
<!-- ====== Design tokens ======================================== -->
|
||||||
|
|
||||||
|
<!-- Card surfaces.
|
||||||
|
Two-tier radius:
|
||||||
|
lg → hero/standalone cards (bank tiles, history header, finance deals, OTP cards)
|
||||||
|
md → repeating row/summary cards (dashboard cards, foreign limit, bottom sheets)
|
||||||
|
Card-visual representations (item_card_*) keep their own larger radius/elevation
|
||||||
|
to read as real credit cards — they are not tokenized. -->
|
||||||
|
<dimen name="card_radius_lg">16dp</dimen>
|
||||||
|
<dimen name="card_radius_md">12dp</dimen>
|
||||||
|
|
||||||
|
<!-- Card elevation. Two tiers:
|
||||||
|
flat → outlined cards (paired with a colorOutlineVariant stroke)
|
||||||
|
raised → subtle Material 3 default raise
|
||||||
|
Larger elevations belong to specific card-visual surfaces only. -->
|
||||||
|
<dimen name="card_elevation_flat">0dp</dimen>
|
||||||
|
<dimen name="card_elevation_raised">1dp</dimen>
|
||||||
|
|
||||||
|
<!-- Screen-level spacing -->
|
||||||
|
<dimen name="screen_margin">16dp</dimen>
|
||||||
|
<dimen name="section_gap">16dp</dimen>
|
||||||
|
|
||||||
|
<!-- Standard list/row padding -->
|
||||||
|
<dimen name="list_item_padding_h">16dp</dimen>
|
||||||
|
<dimen name="list_item_padding_v">14dp</dimen>
|
||||||
|
|
||||||
|
<!-- Gutters: small inline spacing units -->
|
||||||
|
<dimen name="gutter_xs">2dp</dimen>
|
||||||
|
<dimen name="gutter_sm">4dp</dimen>
|
||||||
|
<dimen name="gutter_md">8dp</dimen>
|
||||||
|
<dimen name="gutter_lg">12dp</dimen>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -148,15 +148,6 @@
|
|||||||
<string name="theme_system">System</string>
|
<string name="theme_system">System</string>
|
||||||
<string name="theme_light">Light</string>
|
<string name="theme_light">Light</string>
|
||||||
<string name="theme_dark">Dark</string>
|
<string name="theme_dark">Dark</string>
|
||||||
<string name="settings_pitch_black">Pitch Black</string>
|
|
||||||
<string name="settings_accent_color">Accent Color</string>
|
|
||||||
<string name="accent_blue">Blue</string>
|
|
||||||
<string name="accent_orange">Red</string>
|
|
||||||
<string name="accent_green">Green</string>
|
|
||||||
<string name="accent_custom">Custom</string>
|
|
||||||
<string name="accent_custom_pick">Custom Accent Color</string>
|
|
||||||
<string name="accent_custom_hint">#RRGGBB hex color</string>
|
|
||||||
<string name="accent_invalid_color">Invalid color — enter a valid hex code</string>
|
|
||||||
<string name="language">Language</string>
|
<string name="language">Language</string>
|
||||||
<string name="lang_english">English</string>
|
<string name="lang_english">English</string>
|
||||||
<string name="lang_dhivehi">ދިވެހި</string>
|
<string name="lang_dhivehi">ދިވެހި</string>
|
||||||
@@ -264,6 +255,8 @@
|
|||||||
|
|
||||||
<!-- Accounts -->
|
<!-- Accounts -->
|
||||||
<string name="accounts_empty">No accounts found</string>
|
<string name="accounts_empty">No accounts found</string>
|
||||||
|
<string name="activities_empty">No recent transfers</string>
|
||||||
|
<string name="transactions_empty">No transactions found</string>
|
||||||
|
|
||||||
<!-- Contacts -->
|
<!-- Contacts -->
|
||||||
<string name="contacts_empty">No contacts found</string>
|
<string name="contacts_empty">No contacts found</string>
|
||||||
|
|||||||
@@ -1,37 +1,18 @@
|
|||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<style name="ShapeAppearance.Circle" parent="ShapeAppearance.Material3.Corner.Full" />
|
<style name="ShapeAppearance.Circle" parent="ShapeAppearance.Material3.Corner.Full" />
|
||||||
|
|
||||||
|
<!-- Reusable status chip (filled, secondary container). Apply to a TextView via style. -->
|
||||||
|
<style name="Widget.App.StatusChip" parent="">
|
||||||
|
<item name="android:paddingHorizontal">10dp</item>
|
||||||
|
<item name="android:paddingVertical">4dp</item>
|
||||||
|
<item name="android:background">@drawable/chip_background</item>
|
||||||
|
<item name="android:textAppearance">?attr/textAppearanceLabelSmall</item>
|
||||||
|
<item name="android:textColor">?attr/colorOnSecondaryContainer</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="Theme.BasedBank" parent="Theme.Material3.DayNight.NoActionBar">
|
<style name="Theme.BasedBank" parent="Theme.Material3.DayNight.NoActionBar">
|
||||||
<item name="colorPrimary">@color/seed_primary</item>
|
<item name="colorPrimary">@color/seed_primary</item>
|
||||||
<item name="colorSecondary">@color/seed_secondary</item>
|
<item name="colorSecondary">@color/seed_secondary</item>
|
||||||
<item name="android:windowSoftInputMode">adjustResize</item>
|
<item name="android:windowSoftInputMode">adjustResize</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Accent overlays — applied on API < 31 as fallback when content-based dynamic colors unavailable -->
|
|
||||||
<style name="ThemeOverlay_Accent_Blue" parent="">
|
|
||||||
<item name="colorPrimary">#3F65AD</item>
|
|
||||||
<item name="colorSecondary">#9AD141</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="ThemeOverlay_Accent_Orange" parent="">
|
|
||||||
<item name="colorPrimary">#D32F2F</item>
|
|
||||||
<item name="colorSecondary">#EF9A9A</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="ThemeOverlay_Accent_Green" parent="">
|
|
||||||
<item name="colorPrimary">#4CAF50</item>
|
|
||||||
<item name="colorSecondary">#80CBC4</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<!-- Pitch black overlay — forces pure black surfaces for OLED displays -->
|
|
||||||
<style name="ThemeOverlay_PitchBlack" parent="">
|
|
||||||
<item name="android:colorBackground">#000000</item>
|
|
||||||
<item name="colorSurface">#000000</item>
|
|
||||||
<item name="colorSurfaceVariant">#0d0d0d</item>
|
|
||||||
<item name="colorSurfaceContainer">#0d0d0d</item>
|
|
||||||
<item name="colorSurfaceContainerLow">#000000</item>
|
|
||||||
<item name="colorSurfaceContainerLowest">#000000</item>
|
|
||||||
<item name="colorSurfaceContainerHigh">#1a1a1a</item>
|
|
||||||
<item name="colorSurfaceContainerHighest">#1a1a1a</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user