TP-56343 || Bottomsheet issue and removed fab button from loans tab (#10709)

Co-authored-by: Aman <amankasyapp@gmail.com>
Co-authored-by: Shivam Goyal <shivam.goyal@navi.com>
This commit is contained in:
Aman S
2024-05-07 12:20:01 +05:30
committed by GitHub
parent a039bcd21c
commit 6fa0083408
6 changed files with 132 additions and 184 deletions

View File

@@ -559,6 +559,8 @@ class HomePageActivity :
homeVM.updateProfileDrawerState(false)
} else if (selectedTabId == BottomBarTabType.HOME.name) {
super.onBackPressed()
} else if (selectedTabId == BottomBarTabType.LOAN.name && sharedVM.showBottomSheet.value) {
sharedVM.setBottomSheetState(false)
} else {
navigateToHomeTab()
}

View File

@@ -47,7 +47,6 @@ fun BottomBarWithFabButton(
) {
val expanded = listState().isScrollingUp()
val isInvestmentTabScrollingDown = investmentListState.isScrollingDown()
val isLoanTabScrollingDown = loanTabScrollState.isScrollingDown()
val bottomStickyNudgeData by bottomNavBarVM.bottomStickyNudgeData.collectAsState()
val showBottomBar by homeVM.showBottomBar.collectAsState()
val selectedTabId by sharedVM.selectedTabId.collectAsStateWithLifecycle()
@@ -64,12 +63,11 @@ fun BottomBarWithFabButton(
AppInstallSnackBar(inAppUpdateVM = inAppUpdateVM, homeVM = homeVM)
}
if (
selectedTabId != BottomBarTabType.INSURANCE.name && homeVM.isScanPayFabButtonEnabled()
selectedTabId != BottomBarTabType.INSURANCE.name && selectedTabId != BottomBarTabType.LOAN.name && homeVM.isScanPayFabButtonEnabled()
) {
AnimatedFloatingActionButton(
shouldExpandFabButton = when (selectedTabId) {
BottomBarTabType.HOME.name -> expanded
BottomBarTabType.LOAN.name -> isLoanTabScrollingDown.not()
BottomBarTabType.INVESTMENT.name -> isInvestmentTabScrollingDown.not()
else -> false
},

View File

@@ -1,7 +1,5 @@
package com.naviapp.home.dashboard.ui.compose
import android.app.Activity
import android.view.ViewGroup
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.LocalOverscrollConfiguration
import androidx.compose.foundation.layout.PaddingValues
@@ -11,164 +9,38 @@ import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalBottomSheetLayout
import androidx.compose.material.ModalBottomSheetState
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.Scaffold
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.navi.analytics.utils.NaviTrackEvent
import com.navi.ap.utils.constants.BOTTOM_SHEET_TOP_CORNER_RADIUS
import com.navi.base.utils.orZero
import com.navi.common.listeners.DashboardFragmentListener
import com.navi.uitron.model.UiTronResponse
import com.navi.uitron.render.UiTronRenderer
import com.naviapp.analytics.utils.NaviAnalytics.Companion.PL_POST_MANAGE_LOAN_BOTTOMSHEET_DISMISS
import com.naviapp.forge.model.ScreenDefinition
import com.naviapp.forge.model.WidgetModelDefinition
import com.naviapp.home.dashboard.viewmodels.LoanTabVm
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun LoansTab(
loansTabVm: LoanTabVm = hiltViewModel(),
toggleStatusBarColor: (String, String, String) -> Unit,
dashboardFragmentListener: DashboardFragmentListener? = null,
activity: Activity,
lazyListState: () -> LazyListState?
) {
val loansTabUiTronConfig =
loansTabVm.loansTabUiTronData.collectAsStateWithLifecycle()
val showBottomSheet = loansTabVm.showBottomSheet.collectAsStateWithLifecycle().value
val modalBottomSheetState =
rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
loansTabUiTronConfig.value.let { state ->
if (state is LoanTabVm.LoansTabUiTronScreenState.Success) {
RenderWidgets(
loansTabVm,
state.data,
toggleStatusBarColor,
dashboardFragmentListener,
lazyListState
)
}
}
LaunchedEffect(showBottomSheet) {
when (showBottomSheet) {
true -> {
modalBottomSheetState.show()
activity.showAsBottomSheet(
content = { content ->
RenderBottomSheetContent(
loansTabVm.screenDefinition,
loansTabVm
)
},
modalBottomSheetState = modalBottomSheetState,
viewModel = loansTabVm,
activity = activity
)
}
else -> {
modalBottomSheetState.hide()
NaviTrackEvent.trackEvent(PL_POST_MANAGE_LOAN_BOTTOMSHEET_DISMISS)
}
}
}
}
@OptIn(ExperimentalMaterialApi::class)
fun Activity.showAsBottomSheet(
content: @Composable (() -> Unit) -> Unit,
modalBottomSheetState: ModalBottomSheetState,
viewModel: LoanTabVm,
activity: Activity
) {
val viewGroup = this.findViewById(android.R.id.content) as ViewGroup
addContentToView(viewGroup, content, modalBottomSheetState, viewModel, activity)
}
@OptIn(ExperimentalMaterialApi::class)
private fun addContentToView(
viewGroup: ViewGroup,
content: @Composable (() -> Unit) -> Unit,
modalBottomSheetState: ModalBottomSheetState,
viewModel: LoanTabVm,
activity: Activity
) {
viewGroup.addView(
ComposeView(viewGroup.context).apply {
setContent {
BottomSheetWrapper(
viewGroup,
this,
content,
modalBottomSheetState,
viewModel,
activity
)
}
}
)
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun BottomSheetWrapper(
parent: ViewGroup,
composeView: ComposeView,
content: @Composable (() -> Unit) -> Unit,
modalBottomSheetState: ModalBottomSheetState,
viewModel: LoanTabVm,
activity: Activity
) {
ModalBottomSheetLayout(
sheetShape = RoundedCornerShape(
topStart = BOTTOM_SHEET_TOP_CORNER_RADIUS,
topEnd = BOTTOM_SHEET_TOP_CORNER_RADIUS
),
sheetState = modalBottomSheetState,
sheetContent = {
content {}
}
) {}
LaunchedEffect(modalBottomSheetState.isVisible) {
when (modalBottomSheetState.isVisible) {
false -> {
viewModel.setBottomSheetState(false)
parent.removeView(composeView)
}
else -> {}
}
}
}
@Composable
fun RenderBottomSheetContent(
data: WidgetModelDefinition<UiTronResponse>?,
viewModel: LoanTabVm
) {
renderUitronWidgets(widget = data, viewModel = viewModel)
}
@OptIn(ExperimentalFoundationApi::class)
@@ -177,7 +49,6 @@ fun RenderWidgets(
loansTabVm: LoanTabVm = hiltViewModel(),
data: ScreenDefinition,
toggleStatusBarColor: (String, String, String) -> Unit,
dashboardFragmentListener: DashboardFragmentListener? = null,
lazyListState: () -> LazyListState? = { null }
) {
data.screenStructure?.header?.widgetData?.parentComposeView?.get(0)?.property?.backGroundBrushData?.let {
@@ -187,12 +58,8 @@ fun RenderWidgets(
it.colorStops?.get(1)?.second.toString()
)
}
loansTabVm.handleActions(actionData = data.screenStructure?.renderActions?.postRenderAction)
val scrollState = lazyListState() ?: rememberLazyListState()
val isScrollingDown = scrollState.isScrollingDown()
LaunchedEffect(isScrollingDown) {
dashboardFragmentListener?.toggleFabButton(isScrollingDown.not())
}
Scaffold(
modifier = Modifier
.fillMaxSize(),
@@ -245,26 +112,6 @@ fun LoansTabWidgetRenderer(
}
}
@Composable
private fun LazyListState.isScrollingDown(): Boolean {
var previousIndex by remember(this) { mutableIntStateOf(firstVisibleItemIndex) }
var previousScrollOffset by remember(this) { mutableIntStateOf(firstVisibleItemScrollOffset) }
return remember(this) {
derivedStateOf {
if (previousIndex != firstVisibleItemIndex) {
previousIndex < firstVisibleItemIndex
} else {
previousScrollOffset <= firstVisibleItemScrollOffset
}
.also {
previousIndex = firstVisibleItemIndex
previousScrollOffset = firstVisibleItemScrollOffset
}
}
}
.value
}
@Composable
fun renderUitronWidgets(
widget: WidgetModelDefinition<UiTronResponse>?,

View File

@@ -19,7 +19,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
@@ -33,8 +32,6 @@ class LoanTabVm @Inject constructor(private val repository: LoanTabRepository) :
val redirectionCta = SingleLiveEvent<CtaData>()
var screenDefinition: WidgetModelDefinition<UiTronResponse>? = null
private val _showBottomSheet = MutableStateFlow<Boolean>(false)
val showBottomSheet = _showBottomSheet.asStateFlow()
init {
@@ -110,11 +107,6 @@ class LoanTabVm @Inject constructor(private val repository: LoanTabRepository) :
) : LoansTabUiTronScreenState
}
fun setBottomSheetState(show: Boolean) {
viewModelScope.launch {
_showBottomSheet.emit(show)
}
}
enum class WidgetTypes {
UI_TRON_WIDGET,

View File

@@ -1,6 +1,6 @@
package com.naviapp.home.fragment
import android.content.Context
import android.app.Activity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -8,7 +8,15 @@ import android.view.ViewGroup
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalBottomSheetLayout
import androidx.compose.material.ModalBottomSheetState
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@@ -21,21 +29,24 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.facebook.shimmer.ShimmerFrameLayout
import com.navi.analytics.utils.NaviTrackEvent
import com.navi.ap.utils.constants.BOTTOMSHEET
import com.navi.ap.utils.constants.BOTTOM_SHEET_TOP_CORNER_RADIUS
import com.navi.base.deeplink.DeepLinkManager
import com.navi.base.model.CtaData
import com.navi.base.model.CtaType
import com.navi.base.utils.orFalse
import com.navi.common.listeners.DashboardFragmentListener
import com.navi.common.ui.errorview.FullScreenErrorComposeView
import com.navi.common.utils.Constants.HL_DYNAMIC_MODULE_NAME
import com.navi.common.utils.Constants.PL_DYNAMIC_MODULE_NAME
import com.navi.common.utils.isDynamicModuleInstalled
import com.navi.common.utils.setStatusBarColor
import com.navi.common.utils.setStatusBarColorInt
import com.navi.design.utils.parseColorSafe
import com.navi.uitron.model.UiTronResponse
import com.naviapp.R
import com.naviapp.analytics.utils.NaviAnalytics
import com.naviapp.common.fragment.InfoBottomSheetListener
import com.naviapp.forge.model.WidgetModelDefinition
import com.naviapp.home.dashboard.ui.compose.LoansTab
import com.naviapp.home.dashboard.ui.compose.renderUitronWidgets
import com.naviapp.home.dashboard.viewmodels.LoanTabVm
import com.naviapp.home.model.BottomBarTabType
import com.naviapp.home.viewmodel.SharedVM
@@ -51,13 +62,12 @@ import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class LoanTabFragment(
private val listState: () -> LazyListState? = { null }
) : PaymentBaseFragment(),InfoBottomSheetListener {
) : PaymentBaseFragment(), InfoBottomSheetListener {
private val viewModel by viewModels<LoanTabVm>()
private val sharedVM by lazy {
ViewModelProvider(requireActivity())[SharedVM::class.java]
}
private var dashboardFragmentListener: DashboardFragmentListener? = null
private var isFirstHiddenCallDone = false
override val screenName: String
@@ -72,6 +82,7 @@ class LoanTabFragment(
setContent {
InitTabChangeObserver()
ScreenComposable(listState)
showBottomSheet()
}
}
sendInitEvent()
@@ -95,8 +106,6 @@ class LoanTabFragment(
LoansTab(
loansTabVm = viewModel,
toggleStatusBarColor = ::toggleStatusBarColor,
dashboardFragmentListener = dashboardFragmentListener,
activity = this.requireActivity(),
lazyListState = listState
)
}
@@ -155,15 +164,9 @@ class LoanTabFragment(
)
}
override fun onAttach(context: Context) {
super.onAttach(context)
dashboardFragmentListener = context as? DashboardFragmentListener
}
private fun initObserver() {
viewModel.redirectionCta.observe(viewLifecycleOwner) { ctaData ->
viewModel.setBottomSheetState(false)
sharedVM.setBottomSheetState(false)
navigateTo(ctaData)
}
}
@@ -173,7 +176,7 @@ class LoanTabFragment(
SEE_MORE_BOTTOMSHEET -> {
when (ctaData.type) {
BOTTOMSHEET -> {
viewModel.setBottomSheetState(true)
sharedVM.setBottomSheetState(true)
}
}
}
@@ -201,7 +204,7 @@ class LoanTabFragment(
val symbol = firstOrNull { it.key == PartPrePaymentActivity.SYMBOL }?.value
val paymentType: PaymentType =
PaymentType.get(firstOrNull { it.key == PartPrePaymentActivity.PAYMENT_TYPE }?.value)
loanType = firstOrNull { it.key == com.naviapp.utils.Constants.LOAN_TYPE }?.value
loanType = firstOrNull { it.key == Constants.LOAN_TYPE }?.value
val isPreClosure = false
updatePaymentType(paymentType)
onPaymentClick(
@@ -218,9 +221,7 @@ class LoanTabFragment(
}
private fun handleHiddenChange(hidden: Boolean) {
if (hidden) {
viewModel.setBottomSheetState(false)
} else {
if (hidden.not()) {
if (viewModel.loansTabUiTronData.value is LoanTabVm.LoansTabUiTronScreenState.Success) {
activity?.setStatusBarColorInt(
(viewModel.loansTabUiTronData.value as LoanTabVm.LoansTabUiTronScreenState.Success).data.screenStructure?.header?.widgetData?.parentComposeView?.get(
@@ -247,6 +248,105 @@ class LoanTabFragment(
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun showBottomSheet() {
val showBottomSheet = sharedVM.showBottomSheet.collectAsState().value
val modalBottomSheetState =
rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
LaunchedEffect(showBottomSheet) {
when (showBottomSheet) {
true -> {
modalBottomSheetState.show()
activity?.showAsBottomSheet(
content = { content ->
RenderBottomSheetContent(
viewModel.screenDefinition,
viewModel
)
},
modalBottomSheetState = modalBottomSheetState
)
}
else -> {
modalBottomSheetState.hide()
NaviTrackEvent.trackEvent(NaviAnalytics.PL_POST_MANAGE_LOAN_BOTTOMSHEET_DISMISS)
}
}
}
}
@OptIn(ExperimentalMaterialApi::class)
fun Activity.showAsBottomSheet(
content: @Composable (() -> Unit) -> Unit,
modalBottomSheetState: ModalBottomSheetState
) {
val viewGroup: ViewGroup = this.findViewById(android.R.id.content)
addContentToView(viewGroup, content, modalBottomSheetState)
}
@OptIn(ExperimentalMaterialApi::class)
private fun addContentToView(
viewGroup: ViewGroup,
content: @Composable (() -> Unit) -> Unit,
modalBottomSheetState: ModalBottomSheetState
) {
viewGroup.addView(
ComposeView(viewGroup.context).apply {
setContent {
BottomSheetWrapper(
viewGroup,
this,
content,
modalBottomSheetState
)
}
}
)
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun BottomSheetWrapper(
parent: ViewGroup,
composeView: ComposeView,
content: @Composable (() -> Unit) -> Unit,
modalBottomSheetState: ModalBottomSheetState
) {
ModalBottomSheetLayout(
sheetShape = RoundedCornerShape(
topStart = BOTTOM_SHEET_TOP_CORNER_RADIUS,
topEnd = BOTTOM_SHEET_TOP_CORNER_RADIUS
),
sheetState = modalBottomSheetState,
sheetContent = {
content {}
}
) {}
LaunchedEffect(modalBottomSheetState.isVisible) {
when (modalBottomSheetState.isVisible) {
false -> {
sharedVM.setBottomSheetState(false)
parent.removeView(composeView)
}
else -> {}
}
}
}
@Composable
fun RenderBottomSheetContent(
data: WidgetModelDefinition<UiTronResponse>?,
viewModel: LoanTabVm
) {
renderUitronWidgets(widget = data, viewModel = viewModel)
}
companion object {

View File

@@ -34,6 +34,9 @@ class SharedVM @Inject constructor() : BaseVM() {
private val _selectedTabId = MutableStateFlow(BottomBarTabType.HOME.name)
val selectedTabId = _selectedTabId.asStateFlow()
private val _showBottomSheet = MutableStateFlow(false)
val showBottomSheet = _showBottomSheet.asStateFlow()
fun updateUiTronAction(uiTronActionHandler: UiTronActionHandler?) {
_uiTronActionHandler.update { uiTronActionHandler }
}
@@ -45,4 +48,10 @@ class SharedVM @Inject constructor() : BaseVM() {
fun updateSelectedTabId(tabId: String) {
_selectedTabId.update { tabId }
}
fun setBottomSheetState(show: Boolean) {
viewModelScope.launch {
_showBottomSheet.emit(show)
}
}
}