diff --git a/android/navi-base/src/main/java/com/navi/base/model/BottomSheetData.kt b/android/navi-base/src/main/java/com/navi/base/model/BottomSheetData.kt index ff391b478e..591a92bb1f 100644 --- a/android/navi-base/src/main/java/com/navi/base/model/BottomSheetData.kt +++ b/android/navi-base/src/main/java/com/navi/base/model/BottomSheetData.kt @@ -27,7 +27,8 @@ data class BottomSheetData( @SerializedName("bottomSheetName") var bottomSheetName: String? = null, @SerializedName("isCancelable") var isCancelable: Boolean? = true, @SerializedName("heightAspectRatio") var heightAspectRatio: Double? = null, - @SerializedName("metaData") val metaData: GenericAnalytics? = null + @SerializedName("metaData") val metaData: GenericAnalytics? = null, + @SerializedName("bottomSheetContent") val bottomSheetContent: BottomSheetContent? = null ) : Parcelable, NaviClickAction() @Parcelize @@ -51,3 +52,12 @@ data class Radius( @SerializedName("rightTop") val rightTop: Int? = null, @SerializedName("rightBottom") val rightBottom: Int? = null ) : Parcelable + +@Parcelize +data class BottomSheetContent( + @SerializedName("title") val title: StyledTextWithIconCode? = null, + @SerializedName("subtitle") val subtitle: StyledTextWithIconCode? = null, + @SerializedName("icon") val icon: String? = null, + @SerializedName("infoText") val infoText: StyledTextWithIconCode? = null, + var isInfoTextVisible: Boolean = false +) : Parcelable diff --git a/android/navi-base/src/main/java/com/navi/base/model/NaviClickAction.kt b/android/navi-base/src/main/java/com/navi/base/model/NaviClickAction.kt index 23e62c894b..0a7a80e917 100644 --- a/android/navi-base/src/main/java/com/navi/base/model/NaviClickAction.kt +++ b/android/navi-base/src/main/java/com/navi/base/model/NaviClickAction.kt @@ -31,7 +31,7 @@ data class ActionData( @SerializedName("finish") val finish: Boolean? = null, @SerializedName("clearTask") val clearTask: Boolean? = null, @SerializedName("type") val type: String? = null, - @SerializedName("title") val title: String? = null, + @SerializedName("title") var title: String? = null, @SerializedName("description") val description: String? = null, @SerializedName("primaryAction") val primaryAction: ActionData? = null, @SerializedName("secondaryAction") val secondaryAction: ActionData? = null, @@ -43,7 +43,7 @@ data class ActionData( @SerializedName("metaData") val metaData: GenericAnalytics? = null, @SerializedName("successMessage") val successMessage: String? = null, @SerializedName("disabled") var disabled: Boolean? = null, - @SerializedName("action") val action: String? = null, + @SerializedName("action") var action: String? = null, @SerializedName("bottomSheetData") val bottomSheetData: BottomSheetData? = null, @SerializedName("lottieCode") val lottieCode: String? = null, @SerializedName("secondaryUrl") val secondaryUrl: String? = null, diff --git a/android/navi-common/src/main/java/com/navi/common/model/common/WidgetResponse.kt b/android/navi-common/src/main/java/com/navi/common/model/common/WidgetResponse.kt index 21c2cd37ec..79b7e69256 100644 --- a/android/navi-common/src/main/java/com/navi/common/model/common/WidgetResponse.kt +++ b/android/navi-common/src/main/java/com/navi/common/model/common/WidgetResponse.kt @@ -93,7 +93,8 @@ data class ExtraDataDetails( val buySummaryBottomSheetData: WidgetResponse? = null, @SerializedName("basicDetailsProgress") val basicDetailsProgress: String? = null, @SerializedName("sipInfo") val sipInfo: SipInfo? = null, - @SerializedName("loaderScreen") val loaderScreen: ActionCheckResponse? = null + @SerializedName("loaderScreen") val loaderScreen: ActionCheckResponse? = null, + @SerializedName("isUserInvested") val isUserInvested: Boolean? = null, ) : Parcelable @Parcelize data class CacheConfig(val ttl: Long? = 0, val maxConsumptions: Int? = 0) : Parcelable diff --git a/android/navi-common/src/main/java/com/navi/common/ui/fragment/NewCommonBottomSheet.kt b/android/navi-common/src/main/java/com/navi/common/ui/fragment/NewCommonBottomSheet.kt index 020fc97d45..b390e60eb3 100644 --- a/android/navi-common/src/main/java/com/navi/common/ui/fragment/NewCommonBottomSheet.kt +++ b/android/navi-common/src/main/java/com/navi/common/ui/fragment/NewCommonBottomSheet.kt @@ -11,6 +11,7 @@ import android.graphics.Color import android.os.Bundle import android.view.View import android.view.ViewStub +import androidx.core.view.isVisible import androidx.databinding.DataBindingUtil import com.google.android.material.bottomsheet.BottomSheetBehavior import com.navi.analytics.utils.NaviTrackEvent @@ -19,6 +20,7 @@ import com.navi.base.utils.orZero import com.navi.common.R import com.navi.common.databinding.NewCommonBottomSheetBinding import com.navi.common.listeners.NewBottomSheetListener +import com.navi.common.utils.setStyledText import com.navi.design.textview.NaviTextView import com.navi.design.utils.CornerRadius import com.navi.design.utils.dpToPx @@ -113,7 +115,7 @@ class NewCommonBottomSheet : BaseBottomSheet() { var text = it setButtonLoaderState(binding.primaryBtn, binding.buttonLoader, true, text) } - } else { + } else if (arguments?.getBoolean(SHOULD_DISMISS_BOTTOM_SHEET) == true) { safelyDismissDialog() } } @@ -133,6 +135,18 @@ class NewCommonBottomSheet : BaseBottomSheet() { dpToPxInInt(it.bottomDp.toInt()) ) } + data?.bottomSheetContent?.let { + binding.bottomSheetContent.root.isVisible = true + setStyledText(bottomSheetContent.title, it.title, null) + setStyledText(bottomSheetContent.subtitle, it.subtitle, null) + binding.bottomSheetContent.leftIcon.showWhenDataIsAvailable(it.icon) + if (it.isInfoTextVisible) { + it?.infoText?.let { infoText -> + binding.bottomSheetContent.info.visibility = View.VISIBLE + setStyledText(binding.bottomSheetContent.info, infoText, null) + } + } + } } } @@ -159,6 +173,11 @@ class NewCommonBottomSheet : BaseBottomSheet() { } } + fun updateData(bottomSheetData: BottomSheetData?) { + arguments?.putParcelable(DATA, bottomSheetData) + initUi() + } + override val screenName: String get() = TAG @@ -166,13 +185,19 @@ class NewCommonBottomSheet : BaseBottomSheet() { const val TAG = "NEW_COMMON_BOTTOM_SHEET" private const val DATA = "DATA" private const val IS_BUTTON_LOADER_PRESENT = "IS_START_BUTTON_LOADER" + private const val SHOULD_DISMISS_BOTTOM_SHEET = "SHOULD_DISMISS_BOTTOM_SHEET" - fun getInstance(data: BottomSheetData?, isButtonLoaderPresent: Boolean = false) = + fun getInstance( + data: BottomSheetData?, + isButtonLoaderPresent: Boolean = false, + shouldDismissBottomSheet: Boolean = true + ) = NewCommonBottomSheet().apply { arguments = Bundle().apply { this.putParcelable(DATA, data) putBoolean(IS_BUTTON_LOADER_PRESENT, isButtonLoaderPresent) + putBoolean(SHOULD_DISMISS_BOTTOM_SHEET, shouldDismissBottomSheet) isCancelable = data?.isCancelable == true } } diff --git a/android/navi-common/src/main/res/layout/image_title_and_subtitle.xml b/android/navi-common/src/main/res/layout/image_title_and_subtitle.xml new file mode 100644 index 0000000000..3729756aba --- /dev/null +++ b/android/navi-common/src/main/res/layout/image_title_and_subtitle.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/navi-common/src/main/res/layout/new_common_bottom_sheet.xml b/android/navi-common/src/main/res/layout/new_common_bottom_sheet.xml index c4031a2b2d..c792aa44bb 100644 --- a/android/navi-common/src/main/res/layout/new_common_bottom_sheet.xml +++ b/android/navi-common/src/main/res/layout/new_common_bottom_sheet.xml @@ -42,6 +42,14 @@ android:letterSpacing="0.02" tools:text="Age is not eligible" /> + + > + + @GET("/kuber/static/bottom-sheet/permission") + suspend fun getStaticBottomSheetData( + @Query("type") type: String + ): Response> } \ No newline at end of file diff --git a/android/navi-gold/src/main/java/com/navi/gold/ui/DigitalGoldHomeActivity.kt b/android/navi-gold/src/main/java/com/navi/gold/ui/DigitalGoldHomeActivity.kt index 6bb70a10dc..2cea9b64a3 100644 --- a/android/navi-gold/src/main/java/com/navi/gold/ui/DigitalGoldHomeActivity.kt +++ b/android/navi-gold/src/main/java/com/navi/gold/ui/DigitalGoldHomeActivity.kt @@ -7,14 +7,18 @@ package com.navi.gold.ui +import android.Manifest import android.app.Activity import android.content.Context import android.content.DialogInterface import android.content.Intent +import android.content.pm.PackageManager import android.graphics.Color import android.net.Uri import android.os.Bundle +import android.provider.Settings import android.text.TextUtils +import android.util.Log import android.view.View import android.view.animation.AnimationUtils import android.view.inputmethod.InputMethodManager @@ -22,6 +26,7 @@ import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels import androidx.annotation.StyleRes +import androidx.core.app.ActivityCompat import androidx.core.view.isVisible import androidx.databinding.DataBindingUtil import androidx.fragment.app.FragmentManager @@ -54,6 +59,7 @@ import com.navi.chat.ui.activities.SupportScreenActivity import com.navi.chat.utils.DIGITAL_GOLD import com.navi.chat.utils.GenericScreens import com.navi.chat.utils.NAVI_CHAT_SYSTEM_LOCAL_DATA +import com.navi.common.CommonLibManager import com.navi.common.constants.COLOR_TRANSPARENT import com.navi.common.downloader.DownloadUtil import com.navi.common.enach.ProviderType @@ -64,6 +70,7 @@ import com.navi.common.firebasedb.FirebaseResponse import com.navi.common.firebasedb.FirebaseStatusType import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper import com.navi.common.listeners.NewBottomSheetListener +import com.navi.common.managers.PermissionsManager import com.navi.common.model.ModuleNameV2 import com.navi.common.model.UserDetail import com.navi.common.model.common.InvoiceDownloadData @@ -120,10 +127,13 @@ import com.navi.gold.util.Constants.GOLD_SETUP_SIP import com.navi.gold.util.Constants.GOLD_SIP_DETAILS import com.navi.gold.util.Constants.LOADER import com.navi.gold.util.Constants.GOLD_VALUE +import com.navi.gold.util.Constants.GO_TO_SETTINGS import com.navi.gold.util.Constants.IS_TURBO_CHECKOUT_FLOW +import com.navi.gold.util.Constants.LOCATION_PERMISSION import com.navi.gold.util.Constants.NEXT_CTA import com.navi.gold.util.Constants.PAN_VERIFY_BOTTOM_SHEET import com.navi.gold.util.Constants.PD_RPD_SELECTION +import com.navi.gold.util.Constants.SETTINGS import com.navi.gold.util.Constants.SETUP_SIP_REFRESH import com.navi.gold.util.Constants.SHOW_WIDGET_BOTTOM_SHEET import com.navi.gold.util.Constants.SIP_SETUP_FAILED @@ -139,6 +149,9 @@ import com.navi.gold.util.GoldAnalytics.DIGITAL_GOLD_BUY_SUMMARY_BOTTOM_SHEET_IN import com.navi.gold.util.GoldAnalytics.DIGITAL_GOLD_FOMO_NUDGE_BOTTOM_SHEET_INIT import com.navi.gold.util.GoldAnalytics.DIGITAL_GOLD_HOME_SCREEN import com.navi.gold.util.GoldAnalytics.DIGITAL_GOLD_LANDING_PAGE +import com.navi.gold.util.GoldAnalytics.onLocationPermissionAllowed +import com.navi.gold.util.GoldAnalytics.onLocationPermissionDenied +import com.navi.gold.util.GoldAnalytics.onLocationPermissionDnd import com.navi.gold.util.GoldAnalytics.sendEventsToClickStream import com.navi.gold.util.isTrue import com.navi.gold.util.startExitAnimation @@ -235,6 +248,7 @@ class DigitalGoldHomeActivity : BasePaymentActivity(), WidgetCallback, NewBottom private val naviCheckoutViewModel by lazy { ViewModelProvider(this)[NaviCheckoutViewModel::class.java] } private var widgetBottomSheet: WidgetsSupportedBottomSheet? = null private val transactionViewModel by lazy { ViewModelProvider(this)[DigitalGoldTransactionVM::class.java] } + private val permissionsManager by lazy { PermissionsManager(this) } private var homeResponse: WidgetResponse? = null private var isGoldPriceExpiredReferesh: Boolean? = false @@ -259,6 +273,8 @@ class DigitalGoldHomeActivity : BasePaymentActivity(), WidgetCallback, NewBottom private var isPaymentExpired = false private var paymentCheckFragment: WeakReference? = null private var paymentSdkInitParams: PaymentSdkInitParams? = null + private var nativePermissionPageRequested = false + private var shouldStopGoldConversionWidgetButtonLoaderOnResume = true @Inject lateinit var paymentNavigator: PaymentNavigator private val onPollingEnd = { @@ -431,20 +447,8 @@ class DigitalGoldHomeActivity : BasePaymentActivity(), WidgetCallback, NewBottom naviAdapter.setData(listOfWidgets) } startTimer() - - widgetResponse.extraData?.redirectionCta?.let { redirectionCta -> - onClick(NaviWidgetClickWithActionData(actionData = redirectionCta.toActionData())) - } - widgetResponse.extraData?.sipInfo?.let { sipInfo -> - sipVM.setSipAmount(sipInfo.amount ?: 0.0) - sipVM.setSipFrequency(sipInfo.frequency ?: "") - sipVM.setSipInstallmentDate(sipInfo.installmentDate ?: 1) - } + handleHomeResponseExtraData(widgetResponse) sipVM.setSipReferenceId(widgetResponse.extraData?.sipReferenceId) - - widgetResponse.extraData?.buySummaryBottomSheetData?.let { - homeVM.setBuyBottomSheetData(it) - } } homeVM.pollingData.observeNonNull(this@DigitalGoldHomeActivity) { handlePagePollingData(it) @@ -754,6 +758,36 @@ class DigitalGoldHomeActivity : BasePaymentActivity(), WidgetCallback, NewBottom finish = false ) } + + homeVM.staticBottomSheetData.observeNonNull(this@DigitalGoldHomeActivity) { + setButtonLoaderState(homeResponse, false) + manageUserInteraction(false) + homeVM.setBottomSheetData(it) + showCommonBottomSheet(it, shouldDismissBottomSheet = false) + } + } + + private fun handleHomeResponseExtraData(widgetResponse: WidgetResponse) { + widgetResponse.extraData?.redirectionCta?.let { redirectionCta -> + onClick(NaviWidgetClickWithActionData(actionData = redirectionCta.toActionData())) + } + widgetResponse.extraData?.sipInfo?.let { sipInfo -> + sipVM.setSipAmount(sipInfo.amount ?: 0.0) + sipVM.setSipFrequency(sipInfo.frequency ?: "") + sipVM.setSipInstallmentDate(sipInfo.installmentDate ?: 1) + } + widgetResponse.extraData?.isUserInvested?.let { + homeVM.setUserInvested(isInvested = it) + } + widgetResponse.extraData?.buySummaryBottomSheetData?.let { + if (doesNotHaveLocationAccessForFirstTimeUser()) { + manageUserInteraction(true) + setButtonLoaderState(homeResponse, true) + showLocationPermissionDialog() + } else { + homeVM.setBuyBottomSheetData(it) + } + } } private fun handleTurboCheckoutRedirection() { @@ -1097,7 +1131,8 @@ class DigitalGoldHomeActivity : BasePaymentActivity(), WidgetCallback, NewBottom private fun showCommonBottomSheet( bottomSheetData: BottomSheetData, - isButtonLoaderPresent: Boolean = false + isButtonLoaderPresent: Boolean = false, + shouldDismissBottomSheet: Boolean = true ) { try { if (::commonBottomSheet.isInitialized && commonBottomSheet.isNotNull()) { @@ -1108,7 +1143,8 @@ class DigitalGoldHomeActivity : BasePaymentActivity(), WidgetCallback, NewBottom } commonBottomSheet = NewCommonBottomSheet.getInstance( bottomSheetData, - isButtonLoaderPresent + isButtonLoaderPresent, + shouldDismissBottomSheet ) commonBottomSheet.setListener(this@DigitalGoldHomeActivity) safelyShowBottomSheet(commonBottomSheet, NewCommonBottomSheet.TAG) @@ -1339,7 +1375,7 @@ class DigitalGoldHomeActivity : BasePaymentActivity(), WidgetCallback, NewBottom override val moduleName: ModuleNameV2 = ModuleNameV2.COMMON override fun buttonClick(actionData: ActionData?) { - if (actionData?.action != BUY_GOLD_BOTTOM_SHEET) { + if (actionData?.action != BUY_GOLD_BOTTOM_SHEET && actionData?.action != LOCATION_PERMISSION) { commonBottomSheet.dismiss() } else { isPaymentExpired = true @@ -1369,11 +1405,158 @@ class DigitalGoldHomeActivity : BasePaymentActivity(), WidgetCallback, NewBottom manageUserInteraction(true) fetchGoldBuyBottomSheet() } + + LOCATION_PERMISSION -> { + if (checkForLocationPermission()) { + onLocationPermissionGiven() + } else { + permissionsManager.requestPermissions( + permissions = arrayOf( + Manifest.permission.ACCESS_FINE_LOCATION + ) + ) + } + } + + SETTINGS -> { + openNativePermissionPage() + } } } } } + private fun openNativePermissionPage() { + nativePermissionPageRequested = true + val intent = + Intent( + Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + Uri.parse(com.navi.common.utils.Constants.PACKAGE.plus(CommonLibManager.applicationId)) + ) + startActivity(intent) + } + + override fun onRequestPermissionsResult( + requestCode: Int, permissions: Array, grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + + if (requestCode == PermissionsManager.REQUEST_CODE) { + + sendLocationAnalytics() + + if (checkForHardDenyPermissions( + arrayOf( + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION + ) + ) + ) { + updateBottomSheetDataToOpenNativeSettings() + commonBottomSheet?.updateData(homeVM.getBottomSheetData()) + } else if (checkForLocationPermission()) { + onLocationPermissionGiven() + } else { + if (::commonBottomSheet.isInitialized && commonBottomSheet.isNotNull()) { + commonBottomSheet.dismiss() + } + } + } + } + + private fun sendLocationAnalytics() { + if ( + checkForLocationPermission() + ) { + onLocationPermissionAllowed(screenName = screenName) + } else if ( + checkForLocationPermission().not() && + (ActivityCompat.shouldShowRequestPermissionRationale( + this, + Manifest.permission.ACCESS_FINE_LOCATION + ) || ActivityCompat.shouldShowRequestPermissionRationale( + this, + Manifest.permission.ACCESS_COARSE_LOCATION + )) + ) { + onLocationPermissionDenied(screenName = screenName) + } else { + onLocationPermissionDnd(screenName = screenName) + } + } + + private fun onLocationPermissionGiven() { + + if (::commonBottomSheet.isInitialized && commonBottomSheet.isNotNull()) { + commonBottomSheet.dismiss() + } + + shouldStopGoldConversionWidgetButtonLoaderOnResume = false + + setButtonLoaderState( + response = homeResponse, + state = true + ) + manageUserInteraction(true) + + updateLocation( + data = null, + screenName = screenName, + businessVertical = com.navi.common.utils.Constants.BUSINESS_VERTICAL_GOLD + ) + + onClick( + NaviWidgetClickWithActionData( + actionData = ActionData( + url = NEXT_CTA + ) + ) + ) + } + + private fun updateBottomSheetDataToOpenNativeSettings() { + val bottomSheetData = homeVM.getBottomSheetData() + bottomSheetData?.actionData?.let { + it.title = GO_TO_SETTINGS + it.action = SETTINGS + } + bottomSheetData?.bottomSheetContent?.let { + it.isInfoTextVisible = true + } + homeVM.setBottomSheetData(bottomSheetData) + } + + private fun checkForHardDenyPermissions(permissions: Array): Boolean { + var isHardDenyPermissionClicked = false + + permissions.forEachIndexed { index, _ -> + if ( + ActivityCompat.checkSelfPermission(this, permissions[index]) != + PackageManager.PERMISSION_GRANTED && + ActivityCompat.shouldShowRequestPermissionRationale( + this, + permissions[index] + ) + .not() + ) { + isHardDenyPermissionClicked = true + } + } + + permissions.forEachIndexed { index, _ -> + if ( + ActivityCompat.checkSelfPermission(this, permissions[index]) == + PackageManager.PERMISSION_GRANTED + ) { + if (isHardDenyPermissionClicked) { + isHardDenyPermissionClicked = false + } + } + } + + return isHardDenyPermissionClicked + } + override fun widgetAnalytics(genericAnalyticsData: GenericAnalyticsData?) { genericAnalyticsData?.let { data -> val parameters: HashMap = @@ -1448,14 +1631,25 @@ class DigitalGoldHomeActivity : BasePaymentActivity(), WidgetCallback, NewBottom val bundle = Bundle() bundle.putString(AMOUNT_DATA, homeVM.getActualSellAmount().toString()) if (naviClickAction.actionData?.url.equals(NEXT_CTA)) { + manageUserInteraction(true) - homeVM.fetchPanVerifyCta( - GoldKycPageRequest( - type = naviClickAction.actionData?.type, - amount = homeVM.getActualSellAmount() - ) + setButtonLoaderState( + response = homeResponse, + state = true ) + + if (doesNotHaveLocationAccessForFirstTimeUser()) { + showLocationPermissionDialog() + } else { + homeVM.fetchPanVerifyCta( + GoldKycPageRequest( + type = naviClickAction.actionData?.type, + amount = homeVM.getActualSellAmount() + ) + ) + } return + } else if (naviClickAction.actionData?.url.equals(BUY_GOLD_BOTTOM_SHEET, true)) { val amount = naviClickAction.actionData?.parameters?.firstOrNull() { @@ -1636,6 +1830,19 @@ class DigitalGoldHomeActivity : BasePaymentActivity(), WidgetCallback, NewBottom } } + private fun doesNotHaveLocationAccessForFirstTimeUser(): Boolean { + return ( + homeVM.isUserInvested().not() && + checkForLocationPermission().not() + ) + } + + private fun showLocationPermissionDialog() { + homeVM.fetchStaticBottomSheetData( + type = "LOCATION" + ) + } + private fun updateLoaderState( response: WidgetResponse? = null, @@ -1791,12 +1998,29 @@ class DigitalGoldHomeActivity : BasePaymentActivity(), WidgetCallback, NewBottom override fun onResume() { super.onResume() - setButtonLoaderState(homeResponse, false) + + if (shouldStopGoldConversionWidgetButtonLoaderOnResume) { + setButtonLoaderState(homeResponse, false) + manageUserInteraction(false) + } updateLoaderState(response = homeResponse, state = false) - manageUserInteraction(false) + + if (nativePermissionPageRequested) { + nativePermissionPageRequested = false + if (checkForLocationPermission()) { + onLocationPermissionGiven() + } + } + startTimer() } + private fun checkForLocationPermission(): Boolean { + return ( + permissionsManager.hasPermission(Manifest.permission.ACCESS_FINE_LOCATION) || + permissionsManager.hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == homeVM.getPanVerifyRequestCode()) { diff --git a/android/navi-gold/src/main/java/com/navi/gold/util/Constants.kt b/android/navi-gold/src/main/java/com/navi/gold/util/Constants.kt index 8dc6a7758f..735c581340 100644 --- a/android/navi-gold/src/main/java/com/navi/gold/util/Constants.kt +++ b/android/navi-gold/src/main/java/com/navi/gold/util/Constants.kt @@ -76,4 +76,7 @@ object Constants { const val SIP_DETAILS_SCREEN_URL = "gold/sip/sipDetailsScreen" const val TRANSACTION_KEY = "transactionKey" const val VENDOR_KEY = "vendorKey" + const val LOCATION_PERMISSION = "locationPermission" + const val SETTINGS = "settings" + const val GO_TO_SETTINGS = "Go to settings" } \ No newline at end of file diff --git a/android/navi-gold/src/main/java/com/navi/gold/util/GoldAnalytics.kt b/android/navi-gold/src/main/java/com/navi/gold/util/GoldAnalytics.kt index 9d61b4f845..4e46438396 100644 --- a/android/navi-gold/src/main/java/com/navi/gold/util/GoldAnalytics.kt +++ b/android/navi-gold/src/main/java/com/navi/gold/util/GoldAnalytics.kt @@ -2,12 +2,14 @@ package com.navi.gold.util import androidx.annotation.Keep import com.navi.analytics.utils.NaviTrackEvent +import com.navi.analytics.utils.SCREEN_NAME import com.navi.base.model.ActionData import com.navi.base.model.GenericAnalyticsData import com.navi.base.model.NaviWidgetClickWithActionData import com.navi.base.sharedpref.CommonPrefConstants import com.navi.base.sharedpref.PreferenceManager import com.navi.base.utils.BaseUtils +import okhttp3.internal.toImmutableMap import java.util.concurrent.ConcurrentHashMap @Keep @@ -172,4 +174,37 @@ object GoldAnalytics { mapOf(Pair("screenName", screenName)) ) } + + fun attributeMapWithScreenName( + screenName: String, + attributeMap: Map? = null + ): Map { + attributeMap?.let { + val map = attributeMap.toMutableMap() + map[SCREEN_NAME] = screenName + return map.toImmutableMap() + } + ?: run { + return mapOf(Pair(SCREEN_NAME, screenName)) + } + } + + fun onLocationPermissionAllowed(screenName: String) = + NaviTrackEvent.trackEventOnClickStream( + "naviapp_btn_permission_location_allow", + attributeMapWithScreenName(screenName.orEmpty()) + ) + + fun onLocationPermissionDenied(screenName: String) = + NaviTrackEvent.trackEventOnClickStream( + "naviapp_btn_permission_location_deny", + attributeMapWithScreenName(screenName.orEmpty()) + ) + + fun onLocationPermissionDnd(screenName: String) = + NaviTrackEvent.trackEventOnClickStream( + "naviapp_btn_permission_location_dnd", + attributeMapWithScreenName(screenName.orEmpty()) + ) + } \ No newline at end of file diff --git a/android/navi-gold/src/main/java/com/navi/gold/viewmodels/DigitalGoldHomeVM.kt b/android/navi-gold/src/main/java/com/navi/gold/viewmodels/DigitalGoldHomeVM.kt index 5a93a5e506..4037edbe34 100644 --- a/android/navi-gold/src/main/java/com/navi/gold/viewmodels/DigitalGoldHomeVM.kt +++ b/android/navi-gold/src/main/java/com/navi/gold/viewmodels/DigitalGoldHomeVM.kt @@ -7,13 +7,21 @@ package com.navi.gold.viewmodels +import android.Manifest import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.androidx.lifecycle.SingleLiveEvent +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.navi.base.cache.model.NaviCacheAltSourceEntity +import com.navi.base.cache.repository.NaviCacheRepositoryImpl +import com.navi.base.model.BottomSheetData import com.navi.base.utils.isNull import com.navi.base.utils.orFalse +import com.navi.base.utils.orTrue import com.navi.common.model.common.WidgetBottomSheetData import com.navi.common.model.common.WidgetResponse +import com.navi.common.network.models.RepoResult import com.navi.common.utils.Constants.GOLD import com.navi.common.utils.TemporaryStorageHelper import com.navi.common.viewmodel.BaseVM @@ -25,6 +33,12 @@ import com.navi.gold.repo.DigitalGoldHomeRepo import com.navi.gold.repo.DigitalGoldKycRepo import com.navi.gold.repo.DigitalGoldSipRepo import com.navi.gold.repo.DigitalGoldTransactionRepo +import com.navi.naviwidgets.models.NaviWidget +import com.navi.naviwidgets.models.ParameterValue +import com.navi.naviwidgets.validations.BaseInputValidation +import com.navi.naviwidgets.validations.ValidationJsonDeserializer +import com.navi.naviwidgets.widgets.NaviWidgetJsonDeserializer +import com.navi.naviwidgets.widgets.ParameterValueJsonDeserializer import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import javax.inject.Inject @@ -35,7 +49,8 @@ class DigitalGoldHomeVM @Inject constructor( private val goldKycRepo: DigitalGoldKycRepo, private val goldBuyRepo: DigitalGoldBuyRepo, private val goldTransactionRepo: DigitalGoldTransactionRepo, - private val goldSipRepo: DigitalGoldSipRepo + private val goldSipRepo: DigitalGoldSipRepo, + private val naviCacheRepository: NaviCacheRepositoryImpl ) : BaseVM() { @@ -81,6 +96,14 @@ class DigitalGoldHomeVM @Inject constructor( private var _panVerifyBottomSheetDataPostAction: WidgetBottomSheetData? = null private var isTurboCheckoutFlow: Boolean? = false + private var isUserInvested: Boolean? = false + + private val _staticBottomSheetData: MutableLiveData = MutableLiveData() + val staticBottomSheetData: LiveData + get() = _staticBottomSheetData + + private var bottomSheetData: BottomSheetData? = null + fun setActualSellAmount(actualSellAmount: Double) { this.actualSellAmount = actualSellAmount @@ -263,4 +286,68 @@ class DigitalGoldHomeVM @Inject constructor( fun setIsTurboCheckoutFlow(isTurboCheckout: Boolean) { isTurboCheckoutFlow = isTurboCheckout } + + fun setBottomSheetData(bottomSheetData: BottomSheetData?) { + this.bottomSheetData = bottomSheetData + } + + fun getBottomSheetData(): BottomSheetData? { + return bottomSheetData + } + + fun setUserInvested(isInvested: Boolean) { + this.isUserInvested = isInvested + } + + fun isUserInvested() = isUserInvested.orTrue() + + fun fetchStaticBottomSheetData(type: String) { + coroutineScope.safeLaunch { + + val response: RepoResult = + if (type.isNotEmpty()) { + val cachedResponse = naviCacheRepository.getDataOrFetchFromAltSource( + type+"_gold_bottom_sheet_data", + getDataFromAltSource = { + getStaticBottomSheetDataFromRemote(type) + } + ) + RepoResult( + statusCode = 200, + data = Gson().fromJson( + cachedResponse?.value, + BottomSheetData::class.java + ) + ) + } else { + RepoResult( + statusCode = 400, + data = null + ) + } + + if (response.error == null && response.errors.isNullOrEmpty() && response.data != null) { + _staticBottomSheetData.value = response.data + } else { + setErrorData(response.errors, response.error) + } + } + } + + private suspend fun getStaticBottomSheetDataFromRemote(type: String): NaviCacheAltSourceEntity { + val response = goldHomeRepo.fetchStaticBottomSheetData(type) + if (response.error.isNull() && response.errors.isNullOrEmpty()) { + return NaviCacheAltSourceEntity( + value = Gson().toJson(response.data), + isSuccess = true, + version = 1 + ) + } else { + setErrorData(response.errors, response.error) + return NaviCacheAltSourceEntity( + isSuccess = false + ) + } + } + }