From f468fb92aa963fb3bb5f84a128a8cc8f44d06ca0 Mon Sep 17 00:00:00 2001 From: Balrambhai Sharma Date: Tue, 28 Nov 2023 19:13:00 +0530 Subject: [PATCH] TP-49148 | Removal Of Unnecessary API Calls On Static Pages (#8780) --- .../common/tab/InsuranceTabFragment.kt | 28 +++--- .../navi/insurance/claim/info/ClaimFaqVM.kt | 85 ++++++++++++++++--- .../viewpager/NaviViewPagerFragmentVM.kt | 67 +++++++++++++-- .../common/util/NavigationHandler.kt | 2 + .../common/viewmodel/IncentiviseAutopayVM.kt | 57 ++++++++++++- .../insurance/mock_api_util/MockApiUtil.kt | 19 ++++- .../main/res/layout/shimmer_tab_layout.xml | 46 ++++++++++ navi-insurance/src/main/res/values/styles.xml | 4 +- 8 files changed, 272 insertions(+), 36 deletions(-) create mode 100644 navi-insurance/src/main/res/layout/shimmer_tab_layout.xml diff --git a/app/src/main/java/com/naviapp/common/tab/InsuranceTabFragment.kt b/app/src/main/java/com/naviapp/common/tab/InsuranceTabFragment.kt index ab7b363e29..b2e804b3fd 100644 --- a/app/src/main/java/com/naviapp/common/tab/InsuranceTabFragment.kt +++ b/app/src/main/java/com/naviapp/common/tab/InsuranceTabFragment.kt @@ -6,6 +6,8 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.animation.animateContentSize +import androidx.compose.animation.core.tween import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.LocalOverscrollConfiguration import androidx.compose.foundation.layout.Box @@ -71,7 +73,7 @@ class InsuranceTabFragment : BaseFragment(), WidgetCallback, NewBottomSheetListe private fun observeCtaData() { viewModel.redirectionCta.observe(viewLifecycleOwner) { ctaData -> - ctaData?.let { + ctaData.let { NaviInsuranceDeeplinkNavigator.navigate( requireActivity(), it, @@ -101,7 +103,7 @@ class InsuranceTabFragment : BaseFragment(), WidgetCallback, NewBottomSheetListe val isScrollingDown = listState.isScrollingDown() LaunchedEffect(isScrollingDown) { - dashboardFragmentListener?.toggleFabButton(isScrollingDown.not()) + dashboardFragmentListener?.toggleFabButton(isScrollingDown.not()) } Box( @@ -109,12 +111,17 @@ class InsuranceTabFragment : BaseFragment(), WidgetCallback, NewBottomSheetListe .fillMaxSize() ) { when { - state.isLoading -> Unit - state.data.isNotNull() -> { hideLoader() Scaffold( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .fillMaxSize() + .animateContentSize( + animationSpec = tween( + durationMillis = 600, + delayMillis = 0 + ) + ), topBar = { UiTronRenderer( state.data?.headerWidget?.data, @@ -155,7 +162,6 @@ class InsuranceTabFragment : BaseFragment(), WidgetCallback, NewBottomSheetListe } } } - state.hasErrorOccurred -> { hideLoader() HandleError() @@ -195,10 +201,12 @@ class InsuranceTabFragment : BaseFragment(), WidgetCallback, NewBottomSheetListe } private fun fetchInsuranceTabData() { - showLoader( - isShimmerEffect = false, - shimmerEffectLayout = R.layout.landing_page_shimmer_placeholder - ) + if (viewModel.insuranceTabDataFlow.value.data == null) { + showLoader( + isShimmerEffect = true, + shimmerEffectLayout = R.layout.shimmer_tab_layout + ) + } activity?.let { viewModel.fetchInsuranceTabDetails() } diff --git a/navi-insurance/src/main/java/com/navi/insurance/claim/info/ClaimFaqVM.kt b/navi-insurance/src/main/java/com/navi/insurance/claim/info/ClaimFaqVM.kt index 3794dc684b..5bf76c7e97 100644 --- a/navi-insurance/src/main/java/com/navi/insurance/claim/info/ClaimFaqVM.kt +++ b/navi-insurance/src/main/java/com/navi/insurance/claim/info/ClaimFaqVM.kt @@ -2,12 +2,20 @@ package com.navi.insurance.claim.info import android.os.Bundle import androidx.lifecycle.viewModelScope -import com.navi.insurance.claim.repo.ClaimsRepository -import com.navi.insurance.common.util.ActionHandler -import com.navi.insurance.common.GiBaseVM +import com.google.gson.Gson +import com.navi.base.cache.model.NaviCacheAltSourceEntity +import com.navi.base.cache.repository.NaviCacheRepository import com.navi.common.di.CoroutineDispatcherProvider +import com.navi.common.network.models.RepoResult +import com.navi.common.network.models.isSuccessWithData +import com.navi.insurance.claim.repo.ClaimsRepository +import com.navi.insurance.common.GiBaseVM +import com.navi.insurance.common.models.GenericWidgetResponse import com.navi.insurance.common.models.GiErrorMetaData +import com.navi.insurance.common.util.ActionHandler +import com.navi.insurance.common.util.NavigationHandler import com.navi.insurance.network.ApiErrorTagType +import com.navi.insurance.util.GiRetroFit import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -19,7 +27,9 @@ import javax.inject.Inject class ClaimFaqVM @Inject constructor( private val claimsRepository: ClaimsRepository, private val dispatcher: CoroutineDispatcherProvider, - actionHandler: ActionHandler + private val naviCacheRepository: NaviCacheRepository, + actionHandler: ActionHandler, + @GiRetroFit private val giDeserializer: Gson ) : GiBaseVM(actionHandler) { private val _claimInfoStateFlow = @@ -29,21 +39,76 @@ class ClaimFaqVM @Inject constructor( fun fetchData(arguments: Bundle?) { viewModelScope.launch(dispatcher.io + giBaseExceptionHandler(ApiErrorTagType.CLAIM_FAQ_ERROR.value)) { Timber.d("Arguments : $arguments") - val response = claimsRepository.fetchClaimsFaq( - arguments?.getString(ClaimFaqFragment.ARG_TYPE)!!, - arguments.getString(ClaimFaqFragment.ARG_POLICY_ID)!!, - arguments.getString(ClaimFaqFragment.ARG_INTIMATION_REFERENCE_ID) - ) + val response: RepoResult = + if (arguments?.getString(ClaimFaqFragment.ARG_POLICY_ID) + .equals(NavigationHandler.DEFAULT_POLICY_ID) + ) { + val cachedResponse = naviCacheRepository.getDataOrFetchFromAltSource( + NavigationHandler.DEFAULT_POLICY_ID + "_" + arguments?.getString(ClaimFaqFragment.ARG_TYPE), + getDataFromAltSource = { + getTabDetailsResponse( + arguments?.getString(ClaimFaqFragment.ARG_TYPE), + arguments?.getString(ClaimFaqFragment.ARG_POLICY_ID), + arguments?.getString(ClaimFaqFragment.ARG_INTIMATION_REFERENCE_ID) + ) + }) + RepoResult( + statusCode = 200, + data = giDeserializer.fromJson( + cachedResponse?.value, + GenericWidgetResponse::class.java + ) + ) + } else { + claimsRepository.fetchClaimsFaq( + arguments?.getString(ClaimFaqFragment.ARG_TYPE)!!, + arguments.getString(ClaimFaqFragment.ARG_POLICY_ID)!!, + arguments.getString(ClaimFaqFragment.ARG_INTIMATION_REFERENCE_ID) + ) + } if (response.error == null && response.errors.isNullOrEmpty()) { _claimInfoStateFlow.emit(ClaimInfoViewState.Success(response.data)) } else { _claimInfoStateFlow.emit(ClaimInfoViewState.Failure) logError( response, - GiErrorMetaData(ApiErrorTagType.CLAIM_FAQ_ERROR.value, GiErrorMetaData.FLOW_CLAIMS) + GiErrorMetaData( + ApiErrorTagType.CLAIM_FAQ_ERROR.value, + GiErrorMetaData.FLOW_CLAIMS + ) ) } } } + private suspend fun getTabDetailsResponse( + type: String?, + policyId: String?, + intimationReferenceId: String? + ): NaviCacheAltSourceEntity { + val response = + claimsRepository.fetchClaimsFaq( + type.orEmpty(), + policyId.orEmpty(), + intimationReferenceId + ) + + if (!response.isSuccessWithData()) { + _claimInfoStateFlow.emit(ClaimInfoViewState.Failure) + logError( + response, + GiErrorMetaData(ApiErrorTagType.CLAIM_FAQ_ERROR.value, GiErrorMetaData.FLOW_CLAIMS) + ) + return NaviCacheAltSourceEntity( + isSuccess = false + ) + } + + return NaviCacheAltSourceEntity( + value = Gson().toJson(response.data!!), + isSuccess = true, + version = 1 + ) + } + } \ No newline at end of file diff --git a/navi-insurance/src/main/java/com/navi/insurance/claim/viewpager/NaviViewPagerFragmentVM.kt b/navi-insurance/src/main/java/com/navi/insurance/claim/viewpager/NaviViewPagerFragmentVM.kt index c1acea14ed..6020b76d90 100644 --- a/navi-insurance/src/main/java/com/navi/insurance/claim/viewpager/NaviViewPagerFragmentVM.kt +++ b/navi-insurance/src/main/java/com/navi/insurance/claim/viewpager/NaviViewPagerFragmentVM.kt @@ -2,19 +2,27 @@ package com.navi.insurance.claim.viewpager import android.os.Bundle import androidx.lifecycle.viewModelScope +import com.google.gson.Gson +import com.navi.base.cache.model.NaviCacheAltSourceEntity +import com.navi.base.cache.repository.NaviCacheRepository +import com.navi.common.di.CoroutineDispatcherProvider +import com.navi.common.network.models.RepoResult +import com.navi.common.network.models.isSuccessWithData import com.navi.insurance.claim.repo.ClaimsRepository import com.navi.insurance.common.GiBaseVM import com.navi.insurance.common.deserializer.ParameterValueDeserializer.Companion.KEY_BOTTOM_SHEET_INFO import com.navi.insurance.common.deserializer.ParameterValueDeserializer.Companion.KEY_TOAST_INFO import com.navi.insurance.common.models.BottomSheetInfo +import com.navi.insurance.common.models.GenericWidgetResponse +import com.navi.insurance.common.models.GiErrorMetaData import com.navi.insurance.common.models.ParameterValue import com.navi.insurance.common.models.ToastInfo import com.navi.insurance.common.repository.CommonViewPagerRepository import com.navi.insurance.common.util.ActionHandler -import com.navi.common.di.CoroutineDispatcherProvider -import com.navi.insurance.common.models.GiErrorMetaData +import com.navi.insurance.common.util.NavigationHandler import com.navi.insurance.network.ApiErrorTagType import com.navi.insurance.util.Constants +import com.navi.insurance.util.GiRetroFit import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -26,9 +34,11 @@ class NaviViewPagerFragmentVM @Inject constructor( val actionHandler: ActionHandler, + private val naviCacheRepository: NaviCacheRepository, private val dispatcher: CoroutineDispatcherProvider, private val claimsRepository: ClaimsRepository, - private val commonViewPagerRepository: CommonViewPagerRepository + private val commonViewPagerRepository: CommonViewPagerRepository, + @GiRetroFit private val giDeserializer: Gson ) : GiBaseVM(actionHandler) { private val _viewPagerStateFlow = MutableStateFlow(PagerViewState.Loading) @@ -104,18 +114,59 @@ constructor( private fun fetchClaimInfoTabDetails(policyId: String?) { viewModelScope.launch(dispatcher.main + giBaseExceptionHandler(ApiErrorTagType.FETCH_CLAIM_HI_INFO_TABS_ERROR.value)) { - val response = claimsRepository.fetchClaimInfoTabDetails(policyId!!) + val response: RepoResult = + if (policyId.equals(NavigationHandler.DEFAULT_POLICY_ID)) { + val cachedResponse = naviCacheRepository.getDataOrFetchFromAltSource( + NavigationHandler.DEFAULT_POLICY_ID, + getDataFromAltSource = { + getPageResponseFromAPI(policyId) + }) + RepoResult( + statusCode = 200, + data = giDeserializer.fromJson( + cachedResponse?.value, + GenericWidgetResponse::class.java + ) + ) + } else { + claimsRepository.fetchClaimInfoTabDetails(policyId.orEmpty()) + } if (response.data != null && response.error == null && response.errors.isNullOrEmpty()) { _viewPagerStateFlow.emit(PagerViewState.Success(response.data!!)) } else { - emitError(response, ApiErrorTagType.FETCH_CLAIM_HI_INFO_TABS_ERROR.value, GiErrorMetaData( - methodName = ApiErrorTagType.FETCH_CLAIM_HI_INFO_TABS_ERROR.value, - flowName = GiErrorMetaData.FLOW_CLAIMS - )) + emitError( + response, ApiErrorTagType.FETCH_CLAIM_HI_INFO_TABS_ERROR.value, GiErrorMetaData( + methodName = ApiErrorTagType.FETCH_CLAIM_HI_INFO_TABS_ERROR.value, + flowName = GiErrorMetaData.FLOW_CLAIMS + ) + ) } } } + private suspend fun getPageResponseFromAPI( + policyId: String? + ): NaviCacheAltSourceEntity { + val response = + claimsRepository.fetchClaimInfoTabDetails(policyId.orEmpty()) + + if (!response.isSuccessWithData()) { + emitError(response, ApiErrorTagType.FETCH_CLAIM_HI_INFO_TABS_ERROR.value, GiErrorMetaData( + methodName = ApiErrorTagType.FETCH_CLAIM_HI_INFO_TABS_ERROR.value, + flowName = GiErrorMetaData.FLOW_CLAIMS + )) + return NaviCacheAltSourceEntity( + isSuccess = false + ) + } + + return NaviCacheAltSourceEntity( + value = Gson().toJson(response.data!!), + isSuccess = true, + version = 1 + ) + } + private fun fetchClaimTrackerTabDetails(claimId: String?, claimStatus: String?) { viewModelScope.launch(dispatcher.main + giBaseExceptionHandler(ApiErrorTagType.FETCH_CLAIM_HI_TRACKER_TABS_ERROR.value)) { val response = claimsRepository.fetchClaimTrackerTabDetails(claimId!!, claimStatus) diff --git a/navi-insurance/src/main/java/com/navi/insurance/common/util/NavigationHandler.kt b/navi-insurance/src/main/java/com/navi/insurance/common/util/NavigationHandler.kt index f2cd0d4c45..2b4974c66e 100644 --- a/navi-insurance/src/main/java/com/navi/insurance/common/util/NavigationHandler.kt +++ b/navi-insurance/src/main/java/com/navi/insurance/common/util/NavigationHandler.kt @@ -375,5 +375,7 @@ class NavigationHandler @Inject constructor(private val uiControllerUtil: UiCont const val URL_INSURANCE_TAB_FRAGMENT = "Insurance_tab_page" const val TABULAR_CONTENT_BOTTOMSHEET = "tabular_content_bottomsheet" const val CLAIMS_STEPS_BOTTOM_SHEET = "claims_steps_bottomsheet" + const val SUMMARY_INSURANCE_TAB = "SUMMARY_INSURANCE_TAB" + const val DEFAULT_POLICY_ID = "DEFAULT_POLICY_ID" } } diff --git a/navi-insurance/src/main/java/com/navi/insurance/common/viewmodel/IncentiviseAutopayVM.kt b/navi-insurance/src/main/java/com/navi/insurance/common/viewmodel/IncentiviseAutopayVM.kt index e8b924450e..05002ca693 100644 --- a/navi-insurance/src/main/java/com/navi/insurance/common/viewmodel/IncentiviseAutopayVM.kt +++ b/navi-insurance/src/main/java/com/navi/insurance/common/viewmodel/IncentiviseAutopayVM.kt @@ -3,12 +3,16 @@ package com.navi.insurance.common.viewmodel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope +import com.google.gson.Gson +import com.navi.base.cache.model.NaviCacheAltSourceEntity +import com.navi.base.cache.repository.NaviCacheRepository import com.navi.base.model.CtaData import com.navi.common.constants.VENDOR_NAVI_API import com.navi.common.di.CoroutineDispatcherProvider import com.navi.common.model.ModuleName import com.navi.common.network.models.ErrorMessage import com.navi.common.network.models.RepoResult +import com.navi.common.network.models.isSuccessWithData import com.navi.common.utils.CommonNaviAnalytics import com.navi.common.utils.CommonNaviAnalytics.Companion.GLOBAL_GENERIC_ERRORS import com.navi.insurance.common.GiBaseVM @@ -19,8 +23,10 @@ import com.navi.insurance.common.models.GiErrorMetaData.Companion.FLOW_INCENTIVI import com.navi.insurance.common.repository.IncentiviseAutopayRepository import com.navi.insurance.common.states.IncentiviseAutopayState import com.navi.insurance.common.util.ActionHandler +import com.navi.insurance.common.util.NavigationHandler.Companion.SUMMARY_INSURANCE_TAB import com.navi.insurance.models.response.IncentiviseAutopayResponse import com.navi.insurance.network.ApiErrorTagType +import com.navi.insurance.util.GiRetroFit import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.flow.MutableStateFlow @@ -31,8 +37,10 @@ import javax.inject.Inject @HiltViewModel class IncentiviseAutopayVM @Inject constructor( private val incentiviseAutopayRepository: IncentiviseAutopayRepository, + private val naviCacheRepository: NaviCacheRepository, actionHandler: ActionHandler, - private val dispatcher: CoroutineDispatcherProvider + private val dispatcher: CoroutineDispatcherProvider, + @GiRetroFit private val giDeserializer: Gson ) : GiBaseVM(actionHandler) { private val _incentiviseAutopayResponseStateFlow = @@ -88,9 +96,24 @@ class IncentiviseAutopayVM @Inject constructor( fun fetchIncentiviseAutopayResponse(type: String?, policyId: String?) { viewModelScope.launch(coroutineExceptionHandler(ApiErrorTagType.FETCH_INCENTIVISE_AUTOPAY_ERROR.value)) { - val response: RepoResult? _incentiviseAutopayResponseStateFlow.emit(IncentiviseAutopayState.Loading) - response = incentiviseAutopayRepository.fetchIncentiviseAutopayResponse(type, policyId) + val response: RepoResult = + if (type.equals(SUMMARY_INSURANCE_TAB)) { + val cachedResponse = naviCacheRepository.getDataOrFetchFromAltSource( + SUMMARY_INSURANCE_TAB, + getDataFromAltSource = { + getPageResponseFromAPI(type, policyId) + }) + RepoResult( + statusCode = 200, + data = giDeserializer.fromJson( + cachedResponse?.value, + IncentiviseAutopayResponse::class.java + ) + ) + } else { + incentiviseAutopayRepository.fetchIncentiviseAutopayResponse(type, policyId) + } if (response.error == null && response.errors.isNullOrEmpty() && response.data != null) { _incentiviseAutopayResponseStateFlow.emit(IncentiviseAutopayState.Success(response.data)) } else { @@ -106,6 +129,34 @@ class IncentiviseAutopayVM @Inject constructor( } } + private suspend fun getPageResponseFromAPI( + pageType: String?, + policyId: String? + ): NaviCacheAltSourceEntity { + val response = + incentiviseAutopayRepository.fetchIncentiviseAutopayResponse(pageType, policyId) + + if (!response.isSuccessWithData()) { + _incentiviseAutopayResponseStateFlow.emit(IncentiviseAutopayState.Failure(response.error)) + logError( + response, + GiErrorMetaData( + ApiErrorTagType.FETCH_INCENTIVISE_AUTOPAY_ERROR.value, + FLOW_INCENTIVISE_AUTOPAY + ) + ) + return NaviCacheAltSourceEntity( + isSuccess = false + ) + } + + return NaviCacheAltSourceEntity( + value = Gson().toJson(response.data!!), + isSuccess = true, + version = 1 + ) + } + fun submitEmailDetails(request: EmailDetailRequest) { viewModelScope.launch(coroutineExceptionHandler(ApiErrorTagType.UPDATE_EMAIL_AUTOPAY_ERROR.value)) { val response: RepoResult? diff --git a/navi-insurance/src/main/java/com/navi/insurance/mock_api_util/MockApiUtil.kt b/navi-insurance/src/main/java/com/navi/insurance/mock_api_util/MockApiUtil.kt index bbc8bc8c5f..02bc45c38d 100644 --- a/navi-insurance/src/main/java/com/navi/insurance/mock_api_util/MockApiUtil.kt +++ b/navi-insurance/src/main/java/com/navi/insurance/mock_api_util/MockApiUtil.kt @@ -10,12 +10,24 @@ package com.navi.insurance.mock_api_util import com.google.gson.GsonBuilder import com.google.gson.JsonObject import com.google.gson.JsonParser +import com.navi.common.CommonLibManager import com.navi.common.network.models.RepoResult import com.navi.common.utils.registerUiTronDeSerializers -import com.navi.common.CommonLibManager import com.navi.insurance.R -import com.navi.insurance.common.deserializer.* -import com.navi.insurance.common.models.* +import com.navi.insurance.common.deserializer.ActionDeserializer +import com.navi.insurance.common.deserializer.ChatInputDeserializer +import com.navi.insurance.common.deserializer.ChatMessageDeserializer +import com.navi.insurance.common.deserializer.MakeApiCallActionDeserializer +import com.navi.insurance.common.deserializer.MultiSelectDataDeserializer +import com.navi.insurance.common.deserializer.NaviWidgetDeserializer +import com.navi.insurance.common.deserializer.ParameterValueDeserializer +import com.navi.insurance.common.models.Action +import com.navi.insurance.common.models.ChatFooterInput +import com.navi.insurance.common.models.ChatMessage +import com.navi.insurance.common.models.MakeApiCallActionData +import com.navi.insurance.common.models.NaviWidget +import com.navi.insurance.common.models.ParameterValue +import com.navi.insurance.common.models.RightSideContentData import com.navi.insurance.util.WidgetDataDeserializer import com.navi.naviwidgets.models.GenericWidgetDataInfo import java.lang.reflect.Type @@ -53,3 +65,4 @@ fun mockApiResponse(type: Type, jsonKey: String): RepoResult { val jsonElement = (JsonParser.parseString(dataString) as? JsonObject)?.get(jsonKey) return RepoResult(statusCode = 200, data = customDeserializer.fromJson(jsonElement, type)) } + diff --git a/navi-insurance/src/main/res/layout/shimmer_tab_layout.xml b/navi-insurance/src/main/res/layout/shimmer_tab_layout.xml new file mode 100644 index 0000000000..f19e23607f --- /dev/null +++ b/navi-insurance/src/main/res/layout/shimmer_tab_layout.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/navi-insurance/src/main/res/values/styles.xml b/navi-insurance/src/main/res/values/styles.xml index cd9d24b75d..1e82453c28 100644 --- a/navi-insurance/src/main/res/values/styles.xml +++ b/navi-insurance/src/main/res/values/styles.xml @@ -361,14 +361,14 @@