NTP-2526 | AS | Rr/pan collection (#12655)
This commit is contained in:
@@ -8,13 +8,13 @@
|
||||
package com.navi.coin.ui.compose.screen
|
||||
|
||||
import android.Manifest.permission.READ_CONTACTS
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -23,16 +23,18 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.navi.base.deeplink.DeepLinkManager
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.base.model.CtaType
|
||||
import com.navi.base.utils.isNotNull
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.coin.ui.activity.CoinBaseActivity
|
||||
import com.navi.coin.ui.compose.common.Init
|
||||
import com.navi.coin.utils.constant.Constants.IS_EXPERIMENT_ENABLED
|
||||
import com.navi.coin.utils.constant.Constants.SCREENS.COINS_LOADING_SCREEN_SCREEN_NAME
|
||||
import com.navi.coin.utils.constant.Constants.SCREEN_CONTENT
|
||||
import com.navi.coin.vm.RedemptionStatusVM
|
||||
@@ -55,80 +57,74 @@ import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
fun RedemptionStatusScreen(
|
||||
bundle: Bundle? = null,
|
||||
navigator: DestinationsNavigator,
|
||||
redemptionStatusVM: RedemptionStatusVM = hiltViewModel(),
|
||||
viewModel: RedemptionStatusVM = hiltViewModel(),
|
||||
) {
|
||||
val context = LocalContext.current as Activity
|
||||
val context = LocalContext.current as CoinBaseActivity
|
||||
val screenContent = remember {
|
||||
getGsonBuilders().fromJson(bundle?.getString(SCREEN_CONTENT), ScreenDefinition::class.java)
|
||||
}
|
||||
var isDataReady by remember { mutableStateOf(false) }
|
||||
var isLottiePlayed by remember { mutableStateOf(false) }
|
||||
var isTransactionSuccessful by remember { mutableStateOf(false) }
|
||||
var isExperimentEnabled by remember {
|
||||
mutableStateOf(screenContent?.metaData?.get("isExperimentEnabled").toBoolean())
|
||||
val isExperimentEnabled by remember {
|
||||
mutableStateOf(screenContent?.metaData?.get(IS_EXPERIMENT_ENABLED).toBoolean())
|
||||
}
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
Init(
|
||||
screenName = COINS_LOADING_SCREEN_SCREEN_NAME,
|
||||
activity = context,
|
||||
viewModel = redemptionStatusVM,
|
||||
viewModel = viewModel,
|
||||
navigator = navigator
|
||||
)
|
||||
|
||||
val contactsPermissionState = rememberPermissionState(permission = READ_CONTACTS)
|
||||
LaunchedEffect(key1 = contactsPermissionState) {
|
||||
if (isExperimentEnabled) {
|
||||
redemptionStatusVM.isContactPermissionGranted = contactsPermissionState.status.isGranted
|
||||
redemptionStatusVM.fetchUserData()
|
||||
viewModel.isContactPermissionGranted = contactsPermissionState.status.isGranted
|
||||
viewModel.fetchUserData()
|
||||
}
|
||||
}
|
||||
BackHandler {}
|
||||
|
||||
DisposableEffect(key1 = lifecycleOwner) {
|
||||
val lifecycleEventObserver = viewModel.initLifecycleObserver(context)
|
||||
lifecycleOwner.lifecycle.addObserver(lifecycleEventObserver)
|
||||
onDispose { lifecycleOwner.lifecycle.removeObserver(lifecycleEventObserver) }
|
||||
}
|
||||
|
||||
LaunchedEffect(key1 = isDataReady, key2 = isLottiePlayed, key3 = isTransactionSuccessful) {
|
||||
when {
|
||||
isExperimentEnabled.not() && isLottiePlayed -> {
|
||||
navigator.popBackStack()
|
||||
val cta =
|
||||
CtaAction(
|
||||
ctaData =
|
||||
CtaData(
|
||||
url = COINS_HISTORY_BOTTOMSHEET_CTA,
|
||||
type = CtaType.REDIRECTION_CTA.name
|
||||
)
|
||||
viewModel.nextScreenCtaData =
|
||||
CtaData(
|
||||
url = COINS_HISTORY_BOTTOMSHEET_CTA,
|
||||
type = CtaType.REDIRECTION_CTA.name
|
||||
)
|
||||
cta.ctaData?.let {
|
||||
DeepLinkManager.getDeepLinkListener()
|
||||
?.navigateTo(context, it, finish = false, bundle = bundle)
|
||||
if (viewModel.shouldShowOneProfile(screenContent)) {
|
||||
viewModel.initiateOneProfile(context)
|
||||
} else {
|
||||
viewModel.navigateToNextScreen(context)
|
||||
}
|
||||
}
|
||||
isExperimentEnabled && isLottiePlayed -> {
|
||||
navigator.popBackStack()
|
||||
val bundle = Bundle()
|
||||
|
||||
var cta =
|
||||
CtaAction(
|
||||
ctaData =
|
||||
CtaData(
|
||||
url = COINS_HISTORY_BOTTOMSHEET_CTA,
|
||||
type = CtaType.REDIRECTION_CTA.name
|
||||
)
|
||||
viewModel.navigationBundle = Bundle()
|
||||
viewModel.nextScreenCtaData =
|
||||
CtaData(
|
||||
url = COINS_HISTORY_BOTTOMSHEET_CTA,
|
||||
type = CtaType.REDIRECTION_CTA.name
|
||||
)
|
||||
|
||||
val listContact = redemptionStatusVM.getUserData()
|
||||
val listContact = viewModel.getUserData()
|
||||
if (isTransactionSuccessful && listContact.isNotNull()) {
|
||||
bundle.putString(USER_DATA, listContact.toJson())
|
||||
cta =
|
||||
CtaAction(
|
||||
ctaData =
|
||||
CtaData(
|
||||
url = COINS_HISTORY_CTA,
|
||||
type = CtaType.REDIRECTION_CTA.name
|
||||
)
|
||||
)
|
||||
viewModel.navigationBundle.putString(USER_DATA, listContact.toJson())
|
||||
viewModel.nextScreenCtaData =
|
||||
CtaData(url = COINS_HISTORY_CTA, type = CtaType.REDIRECTION_CTA.name)
|
||||
}
|
||||
|
||||
cta.ctaData?.let {
|
||||
DeepLinkManager.getDeepLinkListener()
|
||||
?.navigateTo(context, it, finish = false, bundle = bundle)
|
||||
if (viewModel.shouldShowOneProfile(screenContent)) {
|
||||
viewModel.initiateOneProfile(context)
|
||||
} else {
|
||||
viewModel.navigateToNextScreen(context)
|
||||
}
|
||||
isDataReady = false
|
||||
isLottiePlayed = false
|
||||
@@ -137,7 +133,7 @@ fun RedemptionStatusScreen(
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
redemptionStatusVM.screenActions.collect { action ->
|
||||
viewModel.screenActions.collect { action ->
|
||||
when (action) {
|
||||
is CtaAction -> {
|
||||
val url = action.ctaData?.url
|
||||
@@ -158,9 +154,9 @@ fun RedemptionStatusScreen(
|
||||
}
|
||||
}
|
||||
Box(modifier = Modifier.fillMaxSize().background(Color.White)) {
|
||||
screenContent?.metaData?.get(SHARE_MESSAGE)?.let { redemptionStatusVM.shareMessage = it }
|
||||
screenContent?.metaData?.get(SHARE_MESSAGE)?.let { viewModel.shareMessage = it }
|
||||
screenContent?.screenStructure?.content?.widgets?.forEach { uiTronWidget ->
|
||||
WidgetRenderer(widget = uiTronWidget, viewModel = redemptionStatusVM)
|
||||
WidgetRenderer(widget = uiTronWidget, viewModel = viewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.coin.utils.analytics
|
||||
|
||||
object EventConstants {
|
||||
const val ONE_PROFILE_INIT_EVENT = "naviapp_oneprofile_onboarding_init"
|
||||
const val ORIGIN_SCREEN = "origin_screen"
|
||||
}
|
||||
@@ -47,6 +47,18 @@ object Constants {
|
||||
const val REDEMPTION_STATUS_SCREEN_CTA_URL = "coin/REDEMPTION_STATUS_SCREEN"
|
||||
const val TOTAL_CASH_REDEEMED = "totalCashRedeemed"
|
||||
const val PHONE_NUMBER = "PhoneNumber"
|
||||
const val HPC = "HPC"
|
||||
const val VERTICAL_TYPE = "verticalType"
|
||||
const val RNR = "RNR"
|
||||
const val APPLICANT_TYPE = "applicantType"
|
||||
const val CUSTOMER = "CUSTOMER"
|
||||
const val JOURNEY_TYPE = "journeyType"
|
||||
const val NON_ONBOARDING = "NON-ONBOARDING"
|
||||
const val SOURCE = "source"
|
||||
const val IS_SKIPPABLE = "isSkippable"
|
||||
const val TRUE = "true"
|
||||
const val SHOULD_SHOW_ONE_PROFILE = "should_show_op"
|
||||
const val IS_EXPERIMENT_ENABLED = "isExperimentEnabled"
|
||||
|
||||
enum class BottomSheetAction {
|
||||
SHOW,
|
||||
|
||||
@@ -7,25 +7,96 @@
|
||||
|
||||
package com.navi.coin.vm
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.base.model.CtaType
|
||||
import com.navi.base.model.LineItem
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.coin.ui.activity.CoinBaseActivity
|
||||
import com.navi.coin.ui.compose.screen.destinations.RedemptionStatusScreenDestination
|
||||
import com.navi.coin.usecase.ContactUseCase
|
||||
import com.navi.coin.utils.analytics.EventConstants.ONE_PROFILE_INIT_EVENT
|
||||
import com.navi.coin.utils.analytics.EventConstants.ORIGIN_SCREEN
|
||||
import com.navi.coin.utils.constant.Constants.APPLICANT_TYPE
|
||||
import com.navi.coin.utils.constant.Constants.CUSTOMER
|
||||
import com.navi.coin.utils.constant.Constants.HPC
|
||||
import com.navi.coin.utils.constant.Constants.IS_SKIPPABLE
|
||||
import com.navi.coin.utils.constant.Constants.JOURNEY_TYPE
|
||||
import com.navi.coin.utils.constant.Constants.NON_ONBOARDING
|
||||
import com.navi.coin.utils.constant.Constants.RNR
|
||||
import com.navi.coin.utils.constant.Constants.SCREENS.TRANSACTION_HISTORY_COINS_SCREEN_NAME
|
||||
import com.navi.coin.utils.constant.Constants.SHOULD_SHOW_ONE_PROFILE
|
||||
import com.navi.coin.utils.constant.Constants.SOURCE
|
||||
import com.navi.coin.utils.constant.Constants.TRUE
|
||||
import com.navi.coin.utils.constant.Constants.VERTICAL_TYPE
|
||||
import com.navi.coin.utils.navigateTo
|
||||
import com.navi.common.forge.model.ScreenDefinition
|
||||
import com.navi.common.navigation.NavArgs
|
||||
import com.navi.common.navigation.NavigationAction
|
||||
import com.navi.common.uitron.model.action.CtaAction
|
||||
import com.navi.common.uitron.model.action.FetchUserRewardsDataAction
|
||||
import com.navi.common.utils.Constants.APP_PLATFORM_APPLICATION_TYPE
|
||||
import com.navi.naviwidgets.utils.AP_LAUNCH
|
||||
import com.navi.rr.referral.models.ReferralContactList
|
||||
import com.navi.rr.utils.NaviRRAnalytics
|
||||
import com.navi.rr.utils.constants.Constants
|
||||
import com.navi.rr.utils.constants.ReferralHomeConstants.COINS_HISTORY_BOTTOMSHEET_CTA
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
@HiltViewModel
|
||||
class RedemptionStatusVM @Inject constructor(private val contactUseCase: ContactUseCase) :
|
||||
CoinBaseVM() {
|
||||
|
||||
private var userContactsAndRewards: ReferralContactList? = null
|
||||
var isContactPermissionGranted: Boolean = false
|
||||
var shareMessage: String = ""
|
||||
|
||||
var nextScreenCtaData: CtaData =
|
||||
CtaData(url = COINS_HISTORY_BOTTOMSHEET_CTA, type = CtaType.REDIRECTION_CTA.name)
|
||||
var navigationBundle: Bundle = bundleOf()
|
||||
|
||||
var isOneProfileJourneyInitiated = MutableStateFlow(false)
|
||||
var shouldPopBackStack = MutableStateFlow(false)
|
||||
|
||||
fun initLifecycleObserver(context: CoinBaseActivity): LifecycleEventObserver {
|
||||
val observer = LifecycleEventObserver { _, event ->
|
||||
when (event) {
|
||||
Lifecycle.Event.ON_PAUSE -> {
|
||||
if (isOneProfileJourneyInitiated.value) {
|
||||
shouldPopBackStack.value = true
|
||||
}
|
||||
}
|
||||
Lifecycle.Event.ON_RESUME -> {
|
||||
if (isOneProfileJourneyInitiated.value && shouldPopBackStack.value) {
|
||||
shouldPopBackStack.value = false
|
||||
isOneProfileJourneyInitiated.value = false
|
||||
navigateToNextScreen(context)
|
||||
}
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
return observer
|
||||
}
|
||||
|
||||
fun navigateToNextScreen(context: CoinBaseActivity) {
|
||||
navigateTo(
|
||||
activity = context,
|
||||
navHostOwner = context,
|
||||
navArgs = NavArgs(ctaData = nextScreenCtaData, bundle = navigationBundle),
|
||||
navAction =
|
||||
NavigationAction.NextWithPopUpTo(
|
||||
route = RedemptionStatusScreenDestination.route,
|
||||
inclusive = true
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun fetchUserData(apiAction: FetchUserRewardsDataAction? = null) {
|
||||
contactUseCase.fetchUserData(
|
||||
apiAction = apiAction,
|
||||
@@ -54,4 +125,47 @@ class RedemptionStatusVM @Inject constructor(private val contactUseCase: Contact
|
||||
userContactsAndRewards?.shareMessage = shareMessage
|
||||
return userContactsAndRewards
|
||||
}
|
||||
|
||||
fun shouldShowOneProfile(screenDefinition: ScreenDefinition): Boolean {
|
||||
return screenDefinition.metaData?.get(SHOULD_SHOW_ONE_PROFILE).toBoolean().orFalse()
|
||||
}
|
||||
|
||||
fun initiateOneProfile(context: CoinBaseActivity) {
|
||||
isOneProfileJourneyInitiated.value = true
|
||||
val listParams =
|
||||
listOf(
|
||||
LineItem(APP_PLATFORM_APPLICATION_TYPE, HPC),
|
||||
LineItem(VERTICAL_TYPE, RNR),
|
||||
LineItem(APPLICANT_TYPE, CUSTOMER)
|
||||
)
|
||||
val listAdditionalParams =
|
||||
listOf(
|
||||
LineItem(JOURNEY_TYPE, NON_ONBOARDING),
|
||||
LineItem(SOURCE, RNR),
|
||||
LineItem(IS_SKIPPABLE, TRUE)
|
||||
)
|
||||
NaviRRAnalytics.naviRRAnalytics
|
||||
.Rewards()
|
||||
.sendEvent(
|
||||
eventName = ONE_PROFILE_INIT_EVENT,
|
||||
extraAttributes =
|
||||
hashMapOf(
|
||||
ORIGIN_SCREEN to TRANSACTION_HISTORY_COINS_SCREEN_NAME,
|
||||
IS_SKIPPABLE to TRUE
|
||||
)
|
||||
)
|
||||
navigateTo(
|
||||
activity = context,
|
||||
navHostOwner = context,
|
||||
navArgs =
|
||||
NavArgs(
|
||||
ctaData =
|
||||
CtaData(
|
||||
url = AP_LAUNCH,
|
||||
parameters = listParams,
|
||||
additionalParameters = listAdditionalParams
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,4 +19,7 @@ sealed class NavigationAction {
|
||||
data object BackWithRefresh : NavigationAction()
|
||||
|
||||
data object Default : NavigationAction()
|
||||
|
||||
data class NextWithPopUpTo(val route: String, val inclusive: Boolean = false) :
|
||||
NavigationAction()
|
||||
}
|
||||
|
||||
@@ -66,6 +66,21 @@ class DefaultComposableNavigatorImpl @Inject constructor() : ComposableNavigator
|
||||
?.set(COMPOSABLE_ID, composableId)
|
||||
}
|
||||
|
||||
private fun nextWithPopUpTo(
|
||||
navHostOwner: NavHostControllerOwner,
|
||||
direction: Direction,
|
||||
composableId: String,
|
||||
route: String,
|
||||
inclusive: Boolean
|
||||
) {
|
||||
navHostOwner.navController.navigate(direction.route) {
|
||||
popUpTo(route = route) { this.inclusive = inclusive }
|
||||
}
|
||||
navHostOwner.navController.currentBackStackEntry
|
||||
?.savedStateHandle
|
||||
?.set(COMPOSABLE_ID, composableId)
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
override fun navigate(
|
||||
navHostOwner: NavHostControllerOwner,
|
||||
@@ -104,6 +119,15 @@ class DefaultComposableNavigatorImpl @Inject constructor() : ComposableNavigator
|
||||
direction = direction,
|
||||
composableId = composableId
|
||||
)
|
||||
is NavigationAction.NextWithPopUpTo -> {
|
||||
nextWithPopUpTo(
|
||||
navHostOwner = navHostOwner,
|
||||
direction = direction,
|
||||
composableId = composableId,
|
||||
route = action.route,
|
||||
inclusive = action.inclusive
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user