TP-00000 | landing page bottom-sheet compose (#6582)
* TP-00000 | landing page bottom-sheet * TP-00000 | refactoring * TP-00000 | used naviText & refactoring * TP-00000 | spotless fix * TP-00000 | rm extra line * TP-00000 | cta handling * TP-00000 | removed extra code * TP-00000 | removed unused imports * TP-00000 | removed unused imports
This commit is contained in:
committed by
GitHub Enterprise
parent
84a4061872
commit
dcad4d2ed2
@@ -27,9 +27,13 @@ android {
|
||||
}
|
||||
}
|
||||
buildFeatures {
|
||||
compose true
|
||||
dataBinding true
|
||||
viewBinding true
|
||||
}
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion compose_version
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2023 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.hl.landingpage.bottomsheet
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.ViewStub
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import coil.compose.AsyncImage
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.base.utils.EMPTY
|
||||
import com.navi.common.ui.fragment.BaseBottomSheet
|
||||
import com.navi.design.font.FontWeightEnum
|
||||
import com.navi.design.theme.getFontWeight
|
||||
import com.navi.design.theme.ttComposeFontFamily
|
||||
import com.navi.hl.R
|
||||
import com.navi.hl.common.listeners.HLCommonBottomSheetListener
|
||||
import com.navi.hl.databinding.BottomSheetHlTitleWithStartAndEndIconBinding
|
||||
import com.navi.hl.landingpage.model.BottomSheetContent
|
||||
import com.navi.hl.utils.NaviHLAnalytics
|
||||
import com.navi.naviwidgets.extensions.NaviText
|
||||
import com.navi.naviwidgets.models.response.TitleWithStartAndEndIconBottomSheetData
|
||||
|
||||
class TitleWithStartAndEndIconBottomSheet : BaseBottomSheet() {
|
||||
|
||||
private lateinit var binding: BottomSheetHlTitleWithStartAndEndIconBinding
|
||||
private var listItems: List<TitleWithStartAndEndIconBottomSheetData> = emptyList()
|
||||
private var listener: HLCommonBottomSheetListener? = null
|
||||
|
||||
override fun setContainerView(viewStub: ViewStub) {
|
||||
viewStub.layoutResource = R.layout.bottom_sheet_hl_title_with_start_and_end_icon
|
||||
binding = DataBindingUtil.getBinding(viewStub.inflate())!!
|
||||
initUI()
|
||||
}
|
||||
|
||||
private fun initUI() {
|
||||
arguments?.getParcelable<BottomSheetContent>(BOTTOM_SHEET_DATA)?.let { bottomSheetContent ->
|
||||
bottomSheetContent.content?.let {
|
||||
listItems = it
|
||||
}
|
||||
}
|
||||
binding.bottomSheetComposeView.setContent {
|
||||
BottomSheetContent()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BottomSheetContent() {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.wrapContentHeight()
|
||||
.padding(16.dp, 0.dp, 16.dp, 8.dp)
|
||||
) {
|
||||
items(listItems) { item ->
|
||||
if (item.showDivider == true)
|
||||
HorizontalDividerView()
|
||||
else
|
||||
TitleWithStartAndEndIconView(item, ::onItemClick)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TitleWithStartAndEndIconView(
|
||||
data: TitleWithStartAndEndIconBottomSheetData,
|
||||
onItemClick: (CtaData) -> Unit
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(0.dp, 16.dp, 0.dp, 24.dp)
|
||||
.clickable { onItemClick(data.cta ?: CtaData()) },
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
AsyncImage(
|
||||
model = data.startIcon?.url,
|
||||
contentDescription = EMPTY,
|
||||
modifier = Modifier
|
||||
.size(
|
||||
width = (data.startIcon?.iconWidth ?: 24).dp,
|
||||
height = (data.startIcon?.iconHeight ?: 24).dp
|
||||
),
|
||||
fallback = painterResource(id = R.drawable.ic_outlined_home_icon),
|
||||
placeholder = painterResource(id = R.drawable.ic_outlined_home_icon),
|
||||
error = painterResource(id = R.drawable.ic_outlined_home_icon),
|
||||
)
|
||||
NaviText(textFieldData = data.title, Modifier.padding(start = 12.dp))
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
AsyncImage(
|
||||
model = data.endIcon?.url,
|
||||
contentDescription = EMPTY,
|
||||
modifier = Modifier
|
||||
.size(
|
||||
width = (data.endIcon?.iconWidth ?: 24).dp,
|
||||
height = (data.endIcon?.iconHeight ?: 24).dp
|
||||
),
|
||||
fallback = painterResource(id = R.drawable.ic_outlined_home_icon),
|
||||
placeholder = painterResource(id = R.drawable.ic_outlined_home_icon),
|
||||
error = painterResource(id = R.drawable.ic_outlined_home_icon),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HorizontalDividerView() {
|
||||
Divider(
|
||||
color = Color(0xFFE3E5E5),
|
||||
thickness = 1.dp,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(0.dp, 0.dp, 0.dp, 8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
private fun onItemClick(ctaData: CtaData) {
|
||||
listener?.onBsCtaClick(ctaData, TAG)
|
||||
}
|
||||
|
||||
fun setBottomSheetListener(listener: HLCommonBottomSheetListener) {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
override val screenName: String
|
||||
get() = NaviHLAnalytics.HL_TITLE_WITH_START_AND_END_ICON_BOTTOM_SHEET
|
||||
|
||||
companion object {
|
||||
private const val BOTTOM_SHEET_DATA = "BOTTOM_SHEET_DATA"
|
||||
const val TAG = "HL_TITLE_WITH_START_AND_END_ICON_BOTTOM_SHEET"
|
||||
|
||||
fun getInstance(bottomSheetData: BottomSheetContent) =
|
||||
TitleWithStartAndEndIconBottomSheet().apply {
|
||||
val bundle = Bundle().apply {
|
||||
putParcelable(BOTTOM_SHEET_DATA, bottomSheetData)
|
||||
}
|
||||
arguments = bundle
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import com.navi.base.utils.BaseUtils
|
||||
import com.navi.common.utils.observeNullable
|
||||
import com.navi.hl.common.customview.HLTopNavigationHeaderInterface
|
||||
import com.navi.hl.common.listeners.BackListener
|
||||
import com.navi.hl.common.listeners.HLCommonBottomSheetListener
|
||||
import com.navi.hl.common.listeners.HLFooterListener
|
||||
import com.navi.hl.common.ui.activity.Navigator
|
||||
import com.navi.hl.common.ui.fragment.HomeLoanBaseFragment
|
||||
@@ -33,13 +34,15 @@ import com.navi.hl.utils.NaviHLAnalytics
|
||||
import com.navi.hl.utils.slideViewFromBottom
|
||||
import com.navi.naviwidgets.adapters.NaviAdapter
|
||||
import com.navi.hl.landingpage.bottomsheet.IconTitleDescriptionInfoCtaBottomSheet
|
||||
import com.navi.hl.landingpage.bottomsheet.TitleWithStartAndEndIconBottomSheet
|
||||
import com.navi.naviwidgets.callbacks.WidgetCallback
|
||||
import com.navi.naviwidgets.models.NaviWidget
|
||||
import com.navi.naviwidgets.viewholder.ViewHolderFactoryImpl
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFooterListener, WidgetCallback {
|
||||
class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFooterListener,
|
||||
WidgetCallback, HLCommonBottomSheetListener {
|
||||
|
||||
private lateinit var binding: FragmentHlLandingPageBinding
|
||||
private val hlLandingPageEventTracker =
|
||||
@@ -147,8 +150,9 @@ class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFoot
|
||||
override fun onClick(naviClickAction: NaviClickAction, widgetId: String?) {
|
||||
when (naviClickAction) {
|
||||
is CtaData -> {
|
||||
navigateTo(naviClickAction, false)
|
||||
openBottomSheet(naviClickAction)
|
||||
}
|
||||
|
||||
is NaviBenefitsItemClick -> {
|
||||
hlLandingPageEventTracker.onBenefitsCardClicked(naviClickAction.ctaData)
|
||||
naviClickAction.ctaData?.url?.let {
|
||||
@@ -168,6 +172,7 @@ class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFoot
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is NaviWidgetClickWithCtaData -> {
|
||||
hlLandingPageEventTracker.onVideoCardClicked(naviClickAction.ctaData)
|
||||
navigateTo(naviClickAction.ctaData, false)
|
||||
@@ -175,6 +180,18 @@ class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFoot
|
||||
}
|
||||
}
|
||||
|
||||
private fun openBottomSheet(ctaData: CtaData?) {
|
||||
viewModel.landingPageResponse.value?.content?.bottomSheetData?.let {
|
||||
val bottomSheet = TitleWithStartAndEndIconBottomSheet.getInstance(it)
|
||||
bottomSheet.setBottomSheetListener(this)
|
||||
if (!isBottomSheetVisible(TitleWithStartAndEndIconBottomSheet.TAG)) {
|
||||
safelyShowBottomSheet(bottomSheet, TitleWithStartAndEndIconBottomSheet.TAG)
|
||||
}
|
||||
} ?: run {
|
||||
navigateTo(ctaData, false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateTo(cta: CtaData?, finish: Boolean = true) {
|
||||
val navigator = activity
|
||||
if (navigator is Navigator) {
|
||||
@@ -183,7 +200,11 @@ class HomeLoanLandingPageFragment : HomeLoanBaseFragment(), BackListener, HLFoot
|
||||
}
|
||||
|
||||
override fun onFooterCtaClick(ctaData: CtaData?) {
|
||||
navigateTo(ctaData, finish = false)
|
||||
openBottomSheet(ctaData)
|
||||
}
|
||||
|
||||
override fun onBsCtaClick(ctaData: CtaData?, bottomSheetType: String) {
|
||||
navigateTo(ctaData, false)
|
||||
}
|
||||
|
||||
override val screenName: String
|
||||
|
||||
@@ -7,11 +7,14 @@
|
||||
|
||||
package com.navi.hl.landingpage.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.hl.common.models.HLFooter
|
||||
import com.navi.hl.common.models.HLHeader
|
||||
import com.navi.naviwidgets.models.NaviWidget
|
||||
import com.navi.naviwidgets.models.response.TextFieldData
|
||||
import com.navi.naviwidgets.models.response.TitleWithStartAndEndIconBottomSheetData
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
data class HLLandingPageResponse(
|
||||
@SerializedName("header") var header: HLHeader? = null,
|
||||
@@ -21,5 +24,11 @@ data class HLLandingPageResponse(
|
||||
|
||||
data class HLLandingPageContent(
|
||||
@SerializedName("widgets") val widgets: List<NaviWidget>? = null,
|
||||
@SerializedName("infoProviderText") val infoProviderText: TextFieldData? = null
|
||||
@SerializedName("infoProviderText") val infoProviderText: TextFieldData? = null,
|
||||
@SerializedName("bottomSheetData") val bottomSheetData: BottomSheetContent? = null
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
data class BottomSheetContent(
|
||||
@SerializedName("content") val content: List<TitleWithStartAndEndIconBottomSheetData>? = null
|
||||
) : Parcelable
|
||||
|
||||
@@ -18,6 +18,7 @@ class HomeLoanLandingPageRepository
|
||||
constructor(private val retrofitService: RetrofitService) : ResponseCallback() {
|
||||
|
||||
suspend fun fetchLandingPageResponse(): RepoResult<HLLandingPageResponse> {
|
||||
return apiResponseCallback(retrofitService.fetchHomeLoanLandingPageResponse())
|
||||
return apiResponseCallback(retrofitService.fetchHomeLoanLandingPageResponse())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -434,11 +434,14 @@ class NaviHLAnalytics private constructor() {
|
||||
const val HL_LANDING_PAGE = "HL_Landing_Page"
|
||||
const val HL_HELP_BOTTOM_SHEET = "New_HL_Help_Bottom_Sheet"
|
||||
const val HL_LOAN_DETAILS_BOTTOM_SHEET = "New_HL_Loan_Details_Bottom_Sheet"
|
||||
const val HL_REVIEW_PROPERTY_DETAILS_BOTTOM_SHEET = "New_HL_Review_Property_Details_Bottom_Sheet"
|
||||
const val HL_REVIEW_PROPERTY_DETAILS_BOTTOM_SHEET =
|
||||
"New_HL_Review_Property_Details_Bottom_Sheet"
|
||||
const val HL_ACC_AGGREGATOR_BOTTOM_SHEET = "New_HL_Account_Aggregator_Bottom_Sheet"
|
||||
const val HL_EMI_PLAN_TAB_SCREEN = "New_HL_Emi_Plan_Tab_Screen"
|
||||
const val HL_EMI_MONTH_SLIDER_BOTTOM_SHEET = "New_HL_Emi_Month_Slider_Bottom_Sheet"
|
||||
const val HL_DOWPAYMENT_RANGE_BOTTOM_SHEET = "New_HL_Downpayment_Range_Bottom_Sheet"
|
||||
const val HL_TITLE_WITH_START_AND_END_ICON_BOTTOM_SHEET =
|
||||
"New_HL_Title_With_Start_And_End_Icon_Bottom_Sheet"
|
||||
|
||||
const val POST_FIX_LANDED = "_Landed"
|
||||
const val POST_FIX_CLICKED = "_Clicked"
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/bottomSheetComposeView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
</layout>
|
||||
@@ -71,3 +71,12 @@ data class GenericWidgetTimerConfig(
|
||||
@SerializedName("insertAt") val insertAt: Int? = null,
|
||||
@SerializedName("baseString") val baseString: String? = null
|
||||
): Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class TitleWithStartAndEndIconBottomSheetData(
|
||||
@SerializedName("startIcon") val startIcon: ImageFieldData? = null,
|
||||
@SerializedName("title") val title: TextFieldData? = null,
|
||||
@SerializedName("endIcon") val endIcon: ImageFieldData? = null,
|
||||
@SerializedName("showDivider") val showDivider: Boolean? = null,
|
||||
@SerializedName("cta") val cta: CtaData? = null
|
||||
) : Parcelable
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2022 by Navi Technologies Limited
|
||||
* * Copyright © 2022-2023 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
@@ -54,9 +54,9 @@ class ProductIntroWithButtonWidgetLayout @JvmOverloads constructor(
|
||||
widgetData.productIntroWithButtonWidgetData?.let { productWidgetData ->
|
||||
binding.tvAction.apply {
|
||||
setOnClickListener {
|
||||
widgetCallback.onClick(NaviWidgetClickWithCtaData(
|
||||
ctaData = productWidgetData.cta
|
||||
))
|
||||
productWidgetData.cta?.let {
|
||||
widgetCallback.onClick(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,4 +99,4 @@ class ProductIntroWithButtonWidgetLayout @JvmOverloads constructor(
|
||||
private const val DEFAULT_SLIDE_PERIOD_TIME = 2000L
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user