forked from shihaam/thijooree
add logout and move add account to settings page
This commit is contained in:
@@ -87,7 +87,6 @@ class HomeActivity : AppCompatActivity() {
|
|||||||
binding.drawerLayout.closeDrawers()
|
binding.drawerLayout.closeDrawers()
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.nav_dashboard -> show(DashboardFragment())
|
R.id.nav_dashboard -> show(DashboardFragment())
|
||||||
R.id.nav_add_account -> startActivity(Intent(this, LoginActivity::class.java))
|
|
||||||
R.id.nav_accounts -> show(AccountsFragment())
|
R.id.nav_accounts -> show(AccountsFragment())
|
||||||
R.id.nav_contacts -> show(ContactsFragment())
|
R.id.nav_contacts -> show(ContactsFragment())
|
||||||
R.id.nav_transfer_history -> show(TransferHistoryFragment())
|
R.id.nav_transfer_history -> show(TransferHistoryFragment())
|
||||||
@@ -225,6 +224,7 @@ class HomeActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun showAutolockWarning() {
|
private fun showAutolockWarning() {
|
||||||
if (warningDialog?.isShowing == true) return
|
if (warningDialog?.isShowing == true) return
|
||||||
|
if (isFinishing || isDestroyed) return
|
||||||
val dialog = MaterialAlertDialogBuilder(this)
|
val dialog = MaterialAlertDialogBuilder(this)
|
||||||
.setTitle(R.string.autolock_warning_title)
|
.setTitle(R.string.autolock_warning_title)
|
||||||
.setMessage(getString(R.string.autolock_warning_message, 10))
|
.setMessage(getString(R.string.autolock_warning_message, 10))
|
||||||
@@ -268,6 +268,25 @@ class HomeActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun relogin() {
|
||||||
|
val store = CredentialStore(this)
|
||||||
|
val hasMib = store.hasMibCredentials()
|
||||||
|
val hasBml = store.hasBmlCredentials()
|
||||||
|
if (!hasMib && !hasBml) {
|
||||||
|
startActivity(Intent(this, LoginActivity::class.java))
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Immediately drop accounts for logged-out banks from the displayed list
|
||||||
|
val current = viewModel.accounts.value ?: emptyList()
|
||||||
|
viewModel.accounts.value = current.filter { acc ->
|
||||||
|
if (!hasMib && !acc.profileType.startsWith("BML")) return@filter false
|
||||||
|
if (!hasBml && acc.profileType.startsWith("BML")) return@filter false
|
||||||
|
true
|
||||||
|
}
|
||||||
|
autoRefresh(store.loadMibCredentials(), store.loadBmlCredentials(), store)
|
||||||
|
}
|
||||||
|
|
||||||
private fun autoRefresh(
|
private fun autoRefresh(
|
||||||
mibCreds: CredentialStore.MibCredentials?,
|
mibCreds: CredentialStore.MibCredentials?,
|
||||||
bmlCreds: CredentialStore.BmlCredentials?,
|
bmlCreds: CredentialStore.BmlCredentials?,
|
||||||
|
|||||||
@@ -2,15 +2,22 @@ package sh.sar.basedbank.ui.home
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
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.biometric.BiometricManager
|
import androidx.biometric.BiometricManager
|
||||||
import androidx.core.os.LocaleListCompat
|
import androidx.core.os.LocaleListCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import android.content.Intent
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import sh.sar.basedbank.BasedBankApp
|
||||||
import sh.sar.basedbank.R
|
import sh.sar.basedbank.R
|
||||||
import sh.sar.basedbank.api.mib.TransactionCache
|
import sh.sar.basedbank.api.mib.TransactionCache
|
||||||
import sh.sar.basedbank.databinding.FragmentSettingsBinding
|
import sh.sar.basedbank.databinding.FragmentSettingsBinding
|
||||||
@@ -18,6 +25,8 @@ import sh.sar.basedbank.ui.onboarding.SecuritySetupFragment
|
|||||||
import sh.sar.basedbank.util.AccountCache
|
import sh.sar.basedbank.util.AccountCache
|
||||||
import sh.sar.basedbank.util.ContactImageCache
|
import sh.sar.basedbank.util.ContactImageCache
|
||||||
import sh.sar.basedbank.util.ContactsCache
|
import sh.sar.basedbank.util.ContactsCache
|
||||||
|
import sh.sar.basedbank.util.CredentialStore
|
||||||
|
import sh.sar.basedbank.ui.login.LoginActivity
|
||||||
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.RecentsCache
|
import sh.sar.basedbank.util.RecentsCache
|
||||||
@@ -90,19 +99,6 @@ class SettingsFragment : Fragment() {
|
|||||||
(activity as? HomeActivity)?.resetAutolockTimer()
|
(activity as? HomeActivity)?.resetAutolockTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear cache
|
|
||||||
binding.btnClearCache.setOnClickListener {
|
|
||||||
val ctx = requireContext()
|
|
||||||
AccountCache.clear(ctx)
|
|
||||||
ContactsCache.clear(ctx)
|
|
||||||
FinancingCache.clear(ctx)
|
|
||||||
ForeignLimitsCache.clear(ctx)
|
|
||||||
RecentsCache.clear(ctx)
|
|
||||||
TransactionCache.clearAll(ctx)
|
|
||||||
ContactImageCache.clearAll(ctx)
|
|
||||||
Toast.makeText(ctx, R.string.settings_cache_cleared, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change lock
|
// Change lock
|
||||||
binding.btnChangeLock.setOnClickListener {
|
binding.btnChangeLock.setOnClickListener {
|
||||||
(requireActivity() as HomeActivity).showWithBackStack(
|
(requireActivity() as HomeActivity).showWithBackStack(
|
||||||
@@ -119,20 +115,187 @@ class SettingsFragment : Fragment() {
|
|||||||
prefs.edit().putBoolean("biometrics_enabled", isChecked).apply()
|
prefs.edit().putBoolean("biometrics_enabled", isChecked).apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add account
|
||||||
|
binding.btnAddAccount.setOnClickListener {
|
||||||
|
startActivity(Intent(requireContext(), LoginActivity::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear cache
|
||||||
|
binding.btnClearCache.setOnClickListener {
|
||||||
|
val ctx = requireContext()
|
||||||
|
clearAllCaches(ctx)
|
||||||
|
Toast.makeText(ctx, R.string.settings_cache_cleared, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
requireActivity().title = getString(R.string.nav_settings)
|
requireActivity().title = getString(R.string.nav_settings)
|
||||||
// Re-read biometrics pref in case it was changed by SecuritySetupFragment
|
|
||||||
val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE)
|
val prefs = requireContext().getSharedPreferences("prefs", Context.MODE_PRIVATE)
|
||||||
if (binding.rowBiometrics.visibility == View.VISIBLE) {
|
if (binding.rowBiometrics.visibility == View.VISIBLE) {
|
||||||
binding.switchBiometrics.isChecked = prefs.getBoolean("biometrics_enabled", false)
|
binding.switchBiometrics.isChecked = prefs.getBoolean("biometrics_enabled", false)
|
||||||
}
|
}
|
||||||
|
buildLoginsSection()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Logins section ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private fun buildLoginsSection() {
|
||||||
|
val ctx = requireContext()
|
||||||
|
val store = CredentialStore(ctx)
|
||||||
|
val container = binding.loginsContainer
|
||||||
|
container.removeAllViews()
|
||||||
|
|
||||||
|
val hasMib = store.hasMibCredentials()
|
||||||
|
val hasBml = store.hasBmlCredentials()
|
||||||
|
|
||||||
|
binding.tvLoginsTitle.visibility = if (hasMib || hasBml) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
|
if (hasMib) {
|
||||||
|
val profile = store.loadMibUserProfile()
|
||||||
|
val displayName = profile?.fullName?.takeIf { it.isNotBlank() } ?: getString(R.string.mib_name)
|
||||||
|
val profileNames = AccountCache.load(ctx)
|
||||||
|
.map { it.profileName }.filter { it.isNotBlank() }.distinct()
|
||||||
|
addLoginRow(container, R.drawable.mib_faisanet_logo, displayName) {
|
||||||
|
showLoginDetails(
|
||||||
|
title = getString(R.string.mib_name),
|
||||||
|
details = buildString {
|
||||||
|
if (!profile?.fullName.isNullOrBlank()) appendLine("${getString(R.string.login_detail_name)}: ${profile!!.fullName}")
|
||||||
|
if (!profile?.email.isNullOrBlank()) appendLine("${getString(R.string.login_detail_email)}: ${profile!!.email}")
|
||||||
|
if (!profile?.mobile.isNullOrBlank()) appendLine("${getString(R.string.login_detail_mobile)}: ${profile!!.mobile}")
|
||||||
|
if (profileNames.isNotEmpty()) {
|
||||||
|
appendLine()
|
||||||
|
appendLine(getString(R.string.login_detail_profiles))
|
||||||
|
profileNames.forEach { appendLine(" • $it") }
|
||||||
|
}
|
||||||
|
}.trim(),
|
||||||
|
onLogout = { confirmLogout(getString(R.string.mib_name)) { logoutMib(store) } }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasBml) {
|
||||||
|
val profile = store.loadBmlUserProfile()
|
||||||
|
val displayName = profile?.fullName?.takeIf { it.isNotBlank() } ?: getString(R.string.bml_name)
|
||||||
|
val profileNames = AccountCache.loadBml(ctx)
|
||||||
|
.map { it.profileName }.filter { it.isNotBlank() }.distinct()
|
||||||
|
addLoginRow(container, R.drawable.bml_logo_vector, displayName) {
|
||||||
|
showLoginDetails(
|
||||||
|
title = getString(R.string.bml_name),
|
||||||
|
details = buildString {
|
||||||
|
if (!profile?.fullName.isNullOrBlank()) appendLine("${getString(R.string.login_detail_name)}: ${profile!!.fullName}")
|
||||||
|
if (!profile?.email.isNullOrBlank()) appendLine("${getString(R.string.login_detail_email)}: ${profile!!.email}")
|
||||||
|
if (!profile?.mobile.isNullOrBlank()) appendLine("${getString(R.string.login_detail_mobile)}: ${profile!!.mobile}")
|
||||||
|
if (!profile?.customerId.isNullOrBlank()) appendLine("${getString(R.string.login_detail_customer_id)}: ${profile!!.customerId}")
|
||||||
|
if (!profile?.idCard.isNullOrBlank()) appendLine("${getString(R.string.login_detail_id_card)}: ${profile!!.idCard}")
|
||||||
|
if (profileNames.isNotEmpty()) {
|
||||||
|
appendLine()
|
||||||
|
appendLine(getString(R.string.login_detail_profiles))
|
||||||
|
profileNames.forEach { appendLine(" • $it") }
|
||||||
|
}
|
||||||
|
}.trim(),
|
||||||
|
onLogout = { confirmLogout(getString(R.string.bml_name)) { logoutBml(store) } }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addLoginRow(
|
||||||
|
container: LinearLayout,
|
||||||
|
logoRes: Int,
|
||||||
|
displayName: String,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
val ctx = requireContext()
|
||||||
|
val dp = ctx.resources.displayMetrics.density
|
||||||
|
|
||||||
|
val row = LinearLayout(ctx).apply {
|
||||||
|
orientation = LinearLayout.HORIZONTAL
|
||||||
|
gravity = Gravity.CENTER_VERTICAL
|
||||||
|
setPadding(0, (12 * dp).toInt(), 0, (12 * dp).toInt())
|
||||||
|
isClickable = true
|
||||||
|
isFocusable = true
|
||||||
|
val ta = ctx.obtainStyledAttributes(intArrayOf(android.R.attr.selectableItemBackground))
|
||||||
|
background = ta.getDrawable(0)
|
||||||
|
ta.recycle()
|
||||||
|
setOnClickListener { onClick() }
|
||||||
|
}
|
||||||
|
|
||||||
|
val logo = ImageView(ctx).apply {
|
||||||
|
setImageResource(logoRes)
|
||||||
|
scaleType = ImageView.ScaleType.CENTER_INSIDE
|
||||||
|
layoutParams = LinearLayout.LayoutParams((36 * dp).toInt(), (36 * dp).toInt()).apply {
|
||||||
|
marginEnd = (12 * dp).toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val tvName = TextView(ctx).apply {
|
||||||
|
text = displayName
|
||||||
|
setTextAppearance(com.google.android.material.R.style.TextAppearance_Material3_BodyLarge)
|
||||||
|
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
|
||||||
|
}
|
||||||
|
|
||||||
|
row.addView(logo)
|
||||||
|
row.addView(tvName)
|
||||||
|
container.addView(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showLoginDetails(title: String, details: String, onLogout: () -> Unit) {
|
||||||
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setTitle(title)
|
||||||
|
.apply { if (details.isNotBlank()) setMessage(details) }
|
||||||
|
.setPositiveButton(R.string.close, null)
|
||||||
|
.setNegativeButton(R.string.settings_logout) { _, _ -> onLogout() }
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun confirmLogout(bankName: String, onConfirm: () -> Unit) {
|
||||||
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setTitle(getString(R.string.settings_logout_confirm_title, bankName))
|
||||||
|
.setMessage(R.string.settings_logout_confirm_message)
|
||||||
|
.setPositiveButton(R.string.settings_logout) { _, _ -> onConfirm() }
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun logoutMib(store: CredentialStore) {
|
||||||
|
val ctx = requireContext()
|
||||||
|
store.clearMibCredentials()
|
||||||
|
ctx.getSharedPreferences("mib_prefs", Context.MODE_PRIVATE).edit().clear().apply()
|
||||||
|
val app = requireActivity().application as BasedBankApp
|
||||||
|
app.accounts = emptyList()
|
||||||
|
app.mibSession = null
|
||||||
|
app.mibProfiles = emptyList()
|
||||||
|
clearAllCaches(ctx)
|
||||||
|
(activity as HomeActivity).relogin()
|
||||||
|
buildLoginsSection()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun logoutBml(store: CredentialStore) {
|
||||||
|
val ctx = requireContext()
|
||||||
|
store.clearBmlCredentials()
|
||||||
|
store.clearBmlSession()
|
||||||
|
val app = requireActivity().application as BasedBankApp
|
||||||
|
app.bmlSession = null
|
||||||
|
app.bmlAccounts = emptyList()
|
||||||
|
clearAllCaches(ctx)
|
||||||
|
(activity as HomeActivity).relogin()
|
||||||
|
buildLoginsSection()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clearAllCaches(ctx: Context) {
|
||||||
|
AccountCache.clear(ctx)
|
||||||
|
ContactsCache.clear(ctx)
|
||||||
|
FinancingCache.clear(ctx)
|
||||||
|
ForeignLimitsCache.clear(ctx)
|
||||||
|
RecentsCache.clear(ctx)
|
||||||
|
TransactionCache.clearAll(ctx)
|
||||||
|
ContactImageCache.clearAll(ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,30 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="16dp">
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvLoginsTitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/settings_logins"
|
||||||
|
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/loginsContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/btnAddAccount"
|
||||||
|
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="24dp"
|
||||||
|
android:text="@string/nav_add_account" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -29,9 +29,6 @@
|
|||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group android:id="@+id/group_system" android:checkableBehavior="single">
|
<group android:id="@+id/group_system" android:checkableBehavior="single">
|
||||||
<item android:id="@+id/nav_add_account"
|
|
||||||
android:icon="@drawable/ic_nav_add_account"
|
|
||||||
android:title="@string/nav_add_account" />
|
|
||||||
<item android:id="@+id/nav_otp"
|
<item android:id="@+id/nav_otp"
|
||||||
android:icon="@drawable/ic_nav_generic"
|
android:icon="@drawable/ic_nav_generic"
|
||||||
android:title="@string/nav_otp" />
|
android:title="@string/nav_otp" />
|
||||||
|
|||||||
@@ -92,6 +92,19 @@
|
|||||||
<string name="settings_cache">ކޭޝް</string>
|
<string name="settings_cache">ކޭޝް</string>
|
||||||
<string name="settings_clear_cache">ކޭޝް ސާފުކުރޭ</string>
|
<string name="settings_clear_cache">ކޭޝް ސާފުކުރޭ</string>
|
||||||
<string name="settings_cache_cleared">ކޭޝް ސާފުކުރެވިއްޖެ</string>
|
<string name="settings_cache_cleared">ކޭޝް ސާފުކުރެވިއްޖެ</string>
|
||||||
|
<string name="settings_logins">ލޮގިންތައް</string>
|
||||||
|
<string name="settings_logout">ލޮގްއައުޓް</string>
|
||||||
|
<string name="settings_logout_confirm_title">%s އިން ލޮގްއައުޓް ވަންތަ؟</string>
|
||||||
|
<string name="settings_logout_confirm_message">ހުރިހާ ކޭޝް ޑޭޓާ ސާފުވެ، ބާކީ ހުރި އެކައުންޓްތައް އަލުން ލޯޑްވާނެ.</string>
|
||||||
|
<string name="login_detail_name">ނަން</string>
|
||||||
|
<string name="login_detail_username">ޔޫޒަރ ނޭމް</string>
|
||||||
|
<string name="login_detail_email">އީމެއިލް</string>
|
||||||
|
<string name="login_detail_mobile">މޮބައިލް</string>
|
||||||
|
<string name="login_detail_customer_id">ކަސްޓަމަ ID</string>
|
||||||
|
<string name="login_detail_id_card">ID ކާޑް</string>
|
||||||
|
<string name="login_detail_profiles">ޕްރޮފައިލްތައް</string>
|
||||||
|
<string name="close">ބަންދު</string>
|
||||||
|
<string name="cancel">ކެންސަލް</string>
|
||||||
|
|
||||||
<!-- Home -->
|
<!-- Home -->
|
||||||
<string name="accounts">އެކައުންޓްތައް</string>
|
<string name="accounts">އެކައުންޓްތައް</string>
|
||||||
|
|||||||
@@ -110,6 +110,19 @@
|
|||||||
<string name="settings_cache">Cache</string>
|
<string name="settings_cache">Cache</string>
|
||||||
<string name="settings_clear_cache">Clear Cache</string>
|
<string name="settings_clear_cache">Clear Cache</string>
|
||||||
<string name="settings_cache_cleared">Cache cleared</string>
|
<string name="settings_cache_cleared">Cache cleared</string>
|
||||||
|
<string name="settings_logins">Logins</string>
|
||||||
|
<string name="settings_logout">Log out</string>
|
||||||
|
<string name="settings_logout_confirm_title">Log out of %s?</string>
|
||||||
|
<string name="settings_logout_confirm_message">All cached data will be cleared and remaining accounts will be refreshed.</string>
|
||||||
|
<string name="login_detail_name">Name</string>
|
||||||
|
<string name="login_detail_username">Username</string>
|
||||||
|
<string name="login_detail_email">Email</string>
|
||||||
|
<string name="login_detail_mobile">Mobile</string>
|
||||||
|
<string name="login_detail_customer_id">Customer ID</string>
|
||||||
|
<string name="login_detail_id_card">ID Card</string>
|
||||||
|
<string name="login_detail_profiles">Profiles</string>
|
||||||
|
<string name="close">Close</string>
|
||||||
|
<string name="cancel">Cancel</string>
|
||||||
|
|
||||||
<!-- Home -->
|
<!-- Home -->
|
||||||
<string name="transfer_same_account">This is your source account</string>
|
<string name="transfer_same_account">This is your source account</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user