TP-00000 | Improve UPI home screen experience (#8830)

This commit is contained in:
shankar yadav
2023-12-04 17:05:43 +05:30
committed by GitHub
parent 62ac4894cd
commit 87bb38ba75
7 changed files with 201 additions and 11 deletions

View File

@@ -85,6 +85,12 @@ object PreferenceManager {
editor.apply()
}
fun remove(key: String) {
val editor = sharedPreferencesForSession.edit()
editor.remove(key)
editor.apply()
}
fun getIntPreference(key: String): Int {
return sharedPreferencesForSession.getInt(key, 0)
}
@@ -257,6 +263,14 @@ object PreferenceManager {
} else setStringPreference(key, value)
}
fun saveIntSecurely(key: String, value: Int) {
if (shouldUseEncryptedSharedPref()) {
val editor = secureSharedPreferencesForSession?.edit()
editor?.putInt(key, value)
editor?.apply()
} else setIntPreference(key, value)
}
fun getSecureString(key: String): String? {
if (shouldUseEncryptedSharedPref()) {
return secureSharedPreferencesForSession?.getString(key, null)
@@ -264,6 +278,13 @@ object PreferenceManager {
return null
}
fun getSecureInt(key: String): Int? {
if (shouldUseEncryptedSharedPref()) {
return secureSharedPreferencesForSession?.getInt(key, 0)
} else getIntPreference(key)
return null
}
fun getSecureStringApp(key: String): String? {
if (shouldUseEncryptedSharedPref()) {
return secureSharedPreferencesForApp?.getString(key, null)

View File

@@ -71,6 +71,7 @@ object FirebaseRemoteConfigHelper {
const val LIGHT_SENSOR_DISABLE = "LIGHT_SENSOR_DISABLE"
const val INTENT_DATA_INSERT_DISABLED = "INTENT_DATA_INSERT_DISABLED"
const val UPI_NUMBER_DISABLED = "UPI_NUMBER_DISABLED"
const val UPI_HOME_JSON_MODIFICATION_DISABLED = "UPI_HOME_JSON_MODIFICATION_DISABLED"
const val ENABLE_CHAT_V2 = "ENABLE_CHAT_V2"
const val UW_INGESTION_POLLING = "UW_INGESTION_POLLING"
const val PD_SPLASH_BUTTON_TEXT = "PD_SPLASH_BUTTON_TEXT"

View File

@@ -22,6 +22,15 @@ class SharedPreferenceRepository {
}
}
suspend fun saveIntValue(key: String, value: Int, encrypt: Boolean = false) =
withContext(Dispatchers.IO) {
if (encrypt) {
PreferenceManager.saveIntSecurely(key = key, value = value)
} else {
PreferenceManager.setIntPreference(key = key, value = value)
}
}
suspend fun getStringValue(key: String, defValue: String = "", encrypt: Boolean = false) =
withContext(Dispatchers.IO) {
if (encrypt) {
@@ -66,4 +75,11 @@ class SharedPreferenceRepository {
} else {
PreferenceManager.getStringPreference(key = key) ?: defValue
}
fun getIntValueOnMainThread(key: String, defValue: Int = 0, encrypt: Boolean = false) =
if (encrypt) {
PreferenceManager.getSecureInt(key = key) ?: defValue
} else {
PreferenceManager.getIntPreference(key = key)
}
}

View File

@@ -37,6 +37,7 @@ import com.navi.pay.onboarding.account.detail.model.view.LinkedAccountEntity
import com.navi.pay.onboarding.account.linked.model.network.CheckBalanceRequest
import com.navi.pay.utils.BANK_ACCOUNT_UNIQUE_ID
import com.navi.pay.utils.NAVI_PAY_LOADER
import com.navi.pay.utils.removeMoreOptionQrSharedPrefData
import com.ramcosta.composedestinations.spec.Direction
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
@@ -237,7 +238,7 @@ class LinkedAccountDetailViewModel @Inject constructor(
notifyError(deleteAccountAPIResponse, tag = "onRemoveAccountFailure")
return@launch
}
removeMoreOptionQrSharedPrefData()
refreshLinkedAccountsUseCase.execute()
updateBottomSheetUIState(showBottomSheet = false)
updateUIState(uiState = LinkedAccountDetailScreenUIState.RemoveAccountSuccess)

View File

@@ -6,6 +6,8 @@ import com.navi.analytics.utils.NaviTrackEvent
import com.navi.base.cache.model.NaviCacheAltSourceEntity
import com.navi.base.cache.repository.NaviCacheRepository
import com.navi.base.utils.EMPTY
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.UPI_HOME_JSON_MODIFICATION_DISABLED
import com.navi.common.network.models.isSuccessWithData
import com.navi.common.uitron.model.action.CtaAction
import com.navi.pay.analytics.NaviPayAnalytics
@@ -43,6 +45,10 @@ import com.navi.pay.utils.BANK_ACCOUNT_TEXT_LAYOUT_ID
import com.navi.pay.utils.HOME_SCREEN_PRIMARY_VPA_LAYOUT_ID
import com.navi.pay.utils.INDICATOR_IMAGE_PENDING_REQUEST_LAYOUT_ID
import com.navi.pay.utils.KEY_MORE_OPTIONS_ACCOUNT_ID
import com.navi.pay.utils.KEY_MORE_OPTIONS_ACCOUNT_NAME
import com.navi.pay.utils.KEY_MORE_OPTIONS_ACCOUNT_QR_LINK
import com.navi.pay.utils.KEY_MORE_OPTIONS_ACCOUNT_VPA
import com.navi.pay.utils.KEY_MORE_OPTIONS_SAVING_ACCOUNT_COUNT
import com.navi.pay.utils.NAVI_PAY_HOME_PAGE_CACHE_KEY
import com.navi.pay.utils.PENDING_REQUEST
import com.navi.pay.utils.PENDING_REQUESTS
@@ -58,6 +64,7 @@ import com.navi.pay.utils.UPI_LITE_NON_BOARDED_STATE
import com.navi.pay.utils.USER_VPA_INFO_COLUMN_LAYOUT_ID
import com.navi.pay.utils.USER_VPA_PLACEHOLDER_IMAGE
import com.navi.pay.utils.VPA_MAX_LENGTH_TO_ELLIPSIZE
import com.navi.pay.utils.updateNaviPayHomeScreenJson
import com.navi.pay.utils.getFormattedAmountWithDecimal
import com.navi.uitron.model.action.AnalyticsAction
import com.navi.uitron.model.action.UpdateDataAction
@@ -223,21 +230,49 @@ class NaviPayHomeViewModel @Inject constructor(
}
private suspend fun saveDefaultSelectedVpa() {
for (vpa in vpaList) {
if (vpa.linkedAccountEntity.isAccountPrimary) {
vpa.isSelected.value = true
selectedVpaEntity = vpa
sharedPreferenceRepository.saveStringValue(
key = KEY_MORE_OPTIONS_ACCOUNT_ID,
value = vpa.linkedAccountEntity.accountId
)
saveDataInSharedPref(vpa)
} else {
vpa.isSelected.value = false
}
}
}
private suspend fun saveDataInSharedPref(vpa: QrVpaEntity) {
val vpaId = vpa.linkedAccountEntity.vpa
val vpaToDisplay = if (vpaId.length > VPA_MAX_LENGTH_TO_ELLIPSIZE) {
vpaId.substring(0, VPA_MAX_LENGTH_TO_ELLIPSIZE - 3) + "..."
} else {
vpaId
}
val bankName =
vpa.linkedAccountEntity.bankName + " " + vpa.linkedAccountEntity.maskedAccountNumber
val qrUri = vpa.qrCodeUri.toString()
sharedPreferenceRepository.saveStringValue(
key = KEY_MORE_OPTIONS_ACCOUNT_ID,
value = vpa.linkedAccountEntity.accountId
)
sharedPreferenceRepository.saveStringValue(
key = KEY_MORE_OPTIONS_ACCOUNT_NAME,
value = bankName
)
sharedPreferenceRepository.saveStringValue(
key = KEY_MORE_OPTIONS_ACCOUNT_VPA,
value = vpaToDisplay
)
sharedPreferenceRepository.saveStringValue(
key = KEY_MORE_OPTIONS_ACCOUNT_QR_LINK,
value = qrUri
)
sharedPreferenceRepository.saveIntValue(
key = KEY_MORE_OPTIONS_SAVING_ACCOUNT_COUNT,
value = getNonCreditVpaListSize()
)
}
fun updateBottomSheetUIState(
showBottomSheet: Boolean? = null,
bottomSheetUIState: HomeBottomSheetType? = null
@@ -368,6 +403,12 @@ class NaviPayHomeViewModel @Inject constructor(
.uiTronConfig[UiTronScreenName.NAVI_PAY_HOME.value]?.uiTronScreenContent
uiTronScreenContent?.let { screenContent ->
if (FirebaseRemoteConfigHelper.getBoolean(UPI_HOME_JSON_MODIFICATION_DISABLED).not()) {
updateNaviPayHomeScreenJson(
sharedPreferenceRepository,
screenContent.content?.widgets?.firstOrNull()?.parentComposeView?.firstOrNull()?.childrenViews
)
}
updateUiState(uiState = NaviPayHomeScreenUIState.Loaded(uiTronScreenContent = screenContent))
}
}
@@ -660,10 +701,7 @@ class NaviPayHomeViewModel @Inject constructor(
updateBottomSheetUIState(showBottomSheet = false)
qrVpaEntity.isSelected.value = true
selectedVpaEntity = qrVpaEntity
sharedPreferenceRepository.saveStringValue(
key = KEY_MORE_OPTIONS_ACCOUNT_ID,
value = qrVpaEntity.linkedAccountEntity.accountId
)
saveDataInSharedPref(qrVpaEntity)
vpaList.forEach {
it.isSelected.value =
it.linkedAccountEntity.accountId == qrVpaEntity.linkedAccountEntity.accountId

View File

@@ -44,6 +44,10 @@ const val KEY_PROVIDER_NAME = "naviPayKeyProviderName"
const val KEY_EXTERNAL_CUSTOMER_ID = "naviPayKeyMerchantCustomerId"
const val KEY_CUSTOMER_STATUS = "customerStatus"
const val KEY_MORE_OPTIONS_ACCOUNT_ID = "moreOptionsAccountId"
const val KEY_MORE_OPTIONS_ACCOUNT_NAME = "moreOptionsAccountName"
const val KEY_MORE_OPTIONS_ACCOUNT_VPA = "moreOptionsAccountVpa"
const val KEY_MORE_OPTIONS_ACCOUNT_QR_LINK = "moreOptionsAccountQrLink"
const val KEY_MORE_OPTIONS_SAVING_ACCOUNT_COUNT = "moreOptionsSavingAccountCount"
const val KEY_IS_FIRST_TRANSACTION_SUCCESSFUL = "naviPayIsFirstTransactionSuccessful"
const val KEY_DB_ENCRYPTION = "naviPayKeyDbEncryption"
@@ -64,11 +68,22 @@ const val KEY_NPCI_TOKEN_EXPIRY_IN_DAYS = "npciTokenExpriyInDays"
const val KEY_BANK_LIST_DB_LAST_REFRESHED_TIMESTAMP = "bankListLastRefreshedTimestamp"
const val KEY_CONFIG_DB_LAST_REFRESHED_TIMESTAMP = "naviPayConfigDbLastRefreshedTimestamp"
const val BANK_ACCOUNT_TEXT = "bankAccountText"
const val UPI_ID_TEXT = "upiIdText"
const val QR_CODE_IMAGE = "qrCodeImage"
const val USER_VPA_INFO_COLUMN = "userVPAInfoColumn"
const val VPA_PLACE_HOLDER_IMAGE = "vpaPlaceholderImage"
const val BANK_ACCOUNT_DOWN_ARROW = "bankAccountDownArrow"
val NAVI_PAY_NON_ENCRYPT_SHARED_PREF_DATA_KEYS = listOf(
KEY_NPCI_TOKEN,
KEY_NPCI_TOKEN_STORED_TIME,
KEY_BANK_LIST_DB_LAST_REFRESHED_TIMESTAMP,
KEY_CONFIG_DB_LAST_REFRESHED_TIMESTAMP
KEY_CONFIG_DB_LAST_REFRESHED_TIMESTAMP,
KEY_MORE_OPTIONS_ACCOUNT_NAME,
KEY_MORE_OPTIONS_ACCOUNT_VPA,
KEY_MORE_OPTIONS_ACCOUNT_QR_LINK,
KEY_MORE_OPTIONS_SAVING_ACCOUNT_COUNT
)
// Shared Preference constants ends here

View File

@@ -15,6 +15,7 @@ import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.Rect
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.ViewTreeObserver
@@ -55,6 +56,7 @@ import coil.request.ImageRequest
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.qrcode.QRCodeWriter
import com.navi.base.sharedpref.PreferenceManager
import com.navi.base.utils.EMPTY
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.NAVI_PAY_INTENT_VPA
@@ -64,9 +66,15 @@ import com.navi.common.utils.capitalize
import com.navi.common.utils.get
import com.navi.pay.R
import com.navi.pay.common.exception.NaviPayApiException
import com.navi.pay.common.repository.SharedPreferenceRepository
import com.navi.pay.common.theme.color.NaviPayColor
import com.navi.pay.common.viewmodel.NaviPayBaseVM
import com.navi.pay.onboarding.account.add.model.view.AccountType
import com.navi.uitron.model.data.ImageData
import com.navi.uitron.model.data.TextData
import com.navi.uitron.model.data.UiTronData
import com.navi.uitron.model.ui.BaseProperty
import com.navi.uitron.model.ui.UiTronView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
@@ -448,6 +456,96 @@ fun SoftwareKeyboardController?.customHide(context: Context, view: View) {
this?.hide()
}
fun updateNaviPayHomeScreenJson(
sharedPreferenceRepository: SharedPreferenceRepository,
uiTronData: List<UiTronView>?
) {
val bankName =
sharedPreferenceRepository.getStringValueOnMainThread(KEY_MORE_OPTIONS_ACCOUNT_NAME)
if (bankName.isEmpty())
return
val vpa =
sharedPreferenceRepository.getStringValueOnMainThread(KEY_MORE_OPTIONS_ACCOUNT_VPA)
val qrLink = sharedPreferenceRepository.getStringValueOnMainThread(
KEY_MORE_OPTIONS_ACCOUNT_QR_LINK
)
val savingAccountCount = sharedPreferenceRepository.getIntValueOnMainThread(
KEY_MORE_OPTIONS_SAVING_ACCOUNT_COUNT
)
updateHomePageJson(uiTronData, bankName, vpa, qrLink, savingAccountCount)
}
private fun updateHomePageJson(
uiTronData: List<UiTronView>?,
bankName: String,
vpa: String,
qrLink: String,
savingAccountCount: Int
) {
uiTronData?.forEach { childView ->
updateHomePageJsonData(childView.data, bankName, vpa, qrLink)
updateHomePageJsonProperty(childView.property, savingAccountCount)
updateHomePageJson(childView.childrenViews, bankName, vpa, qrLink, savingAccountCount)
}
}
private fun updateHomePageJsonData(
data: MutableMap<String, UiTronData?>?,
bankName: String,
vpa: String,
qrLink: String,
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
data?.forEach { (key, value) ->
when (key) {
BANK_ACCOUNT_TEXT -> {
(value as TextData).text = bankName
}
UPI_ID_TEXT -> {
(value as TextData).text = vpa
}
QR_CODE_IMAGE -> {
if (value is ImageData) {
data[QR_CODE_IMAGE] = ImageData(qrLink)
}
}
}
}
}
}
private fun updateHomePageJsonProperty(
data: BaseProperty?,
savingAccountCount: Int,
) {
when (data?.layoutId) {
USER_VPA_INFO_COLUMN -> {
data.visible = true
}
VPA_PLACE_HOLDER_IMAGE -> {
data.visible = false
}
BANK_ACCOUNT_DOWN_ARROW -> {
data.visible = savingAccountCount > 1
}
}
}
fun removeMoreOptionQrSharedPrefData() {
PreferenceManager.clearKeyBasedSessionPreferenceData(
listOf(
KEY_MORE_OPTIONS_ACCOUNT_NAME,
KEY_MORE_OPTIONS_ACCOUNT_VPA,
KEY_MORE_OPTIONS_ACCOUNT_QR_LINK,
KEY_MORE_OPTIONS_SAVING_ACCOUNT_COUNT
)
)
}
fun isNaviPayOriginatedIntent(uri: Uri): Boolean {
try {
val decodeUri = Uri.decode(uri.toString())