NTP-19767 | Masthead (#14544)
Co-authored-by: Ankit <ankit.yadav@navi.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import com.navi.common.model.ModuleNameV2
|
||||
import com.navi.common.network.ApiConstants
|
||||
import com.navi.common.utils.TemporaryStorageHelper
|
||||
import com.navi.uitron.model.action.UpdateDataAction
|
||||
import com.navi.uitron.model.action.UpdateViewStateAction
|
||||
import com.navi.uitron.model.data.TextData
|
||||
import com.naviapp.analytics.utils.NaviAnalytics
|
||||
import com.naviapp.common.transformer.AppLoadTimerMapper
|
||||
@@ -23,10 +24,12 @@ import com.naviapp.home.reducer.HpEvents
|
||||
import com.naviapp.home.viewmodel.HomeViewModel
|
||||
import com.naviapp.network.di.DataDeserializers
|
||||
import com.naviapp.screenOverlay.utils.PopupConstants.NOTIFICATION_ICON_ANIMATE
|
||||
import com.naviapp.utils.Constants.HomePageConstants.ALPHA
|
||||
import com.naviapp.utils.Constants.HomePageConstants.NAVI_APP_NAV_HOME_PAGE_VIEWED
|
||||
import com.naviapp.utils.Constants.HomePageConstants.NAVI_APP_NAV_INSURANCE_PAGE_VIEWED
|
||||
import com.naviapp.utils.Constants.HomePageConstants.NAVI_APP_NAV_INVESTMENT_PAGE_VIEWED
|
||||
import com.naviapp.utils.Constants.HomePageConstants.NAVI_APP_NAV_LOAN_PAGE_VIEWED
|
||||
import com.naviapp.utils.Constants.HomePageConstants.TOP_NAV_ARC_BACKGROUND
|
||||
import com.naviapp.utils.Constants.Notification.HIDE_NOTIFICATION_COUNT
|
||||
import com.naviapp.utils.Constants.Notification.NINE_PLUS
|
||||
import com.naviapp.utils.Constants.Notification.NOTIFICATION_COUNT_TEXT
|
||||
@@ -64,9 +67,19 @@ constructor(
|
||||
animateInAppNotificationIcon(effects.shouldAnimate, homeVM)
|
||||
is HpEffects.HomePageUiRenderedEvent -> homeVM.logOnDataDisplayedEvent()
|
||||
is HpEffects.TopNavRevealedAnalytics -> naviAnalyticsEventTracker.topNavRevealed()
|
||||
is HpEffects.UpdateMastheadIconsState ->
|
||||
updateMastheadIconsState(effects.alphaFactor, homeVM)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateMastheadIconsState(alphaFactor: Int, homeVM: HomeViewModel) {
|
||||
homeVM.handleAction(
|
||||
UpdateViewStateAction(
|
||||
viewStates = mapOf(TOP_NAV_ARC_BACKGROUND to ALPHA.plus(alphaFactor))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun animateInAppNotificationIcon(shouldAnimate: Boolean, homeVM: HomeViewModel) {
|
||||
if (shouldAnimate) {
|
||||
homeVM.state.value.collapsingToolbar
|
||||
|
||||
@@ -27,6 +27,7 @@ import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.TileMode
|
||||
import androidx.compose.ui.graphics.isSpecified
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -38,7 +39,11 @@ import com.navi.naviwidgets.R
|
||||
import com.navi.naviwidgets.utils.NaviWidgetIconUtils.getImageFromIconCode
|
||||
import com.naviapp.home.utils.shimmerEffect
|
||||
|
||||
fun Modifier.bottomShadow(showShadow: Boolean = true, elevation: Float = 24f): Modifier =
|
||||
fun Modifier.bottomShadow(
|
||||
showShadow: Boolean = true,
|
||||
elevation: Float = 24f,
|
||||
shadowLengthFactor: Int = 2,
|
||||
): Modifier =
|
||||
this.then(
|
||||
Modifier.drawBehind {
|
||||
drawRect(
|
||||
@@ -46,9 +51,14 @@ fun Modifier.bottomShadow(showShadow: Boolean = true, elevation: Float = 24f): M
|
||||
when (showShadow) {
|
||||
true ->
|
||||
Brush.verticalGradient(
|
||||
colors = listOf(Color.Black.copy(0.09f), Color.Transparent),
|
||||
colorStops =
|
||||
arrayOf(
|
||||
Pair(0.22f, Color(0XFFB0C0D9).copy(alpha = 0.12f)),
|
||||
Pair(1f, Color.Transparent),
|
||||
),
|
||||
startY = size.height,
|
||||
endY = size.height + elevation.times(2),
|
||||
endY = size.height + elevation.times(shadowLengthFactor),
|
||||
tileMode = TileMode.Decal,
|
||||
)
|
||||
false ->
|
||||
Brush.verticalGradient(
|
||||
@@ -56,7 +66,7 @@ fun Modifier.bottomShadow(showShadow: Boolean = true, elevation: Float = 24f): M
|
||||
)
|
||||
},
|
||||
topLeft = Offset(0f, size.height),
|
||||
size = Size(size.width, elevation.times(2)),
|
||||
size = Size(size.width, elevation.times(shadowLengthFactor)),
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -17,6 +17,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.navi.paymentclients.viewmodel.base.PaymentManager
|
||||
import com.naviapp.analytics.utils.NaviAnalytics
|
||||
import com.naviapp.common.viewmodel.BottomNavBarVM
|
||||
@@ -48,6 +49,7 @@ fun NavGraphNavigationItem(
|
||||
nudgeState: () -> NudgeState,
|
||||
paymentManager: PaymentManager,
|
||||
) {
|
||||
val uiController = rememberSystemUiController()
|
||||
when (tabId) {
|
||||
NavigationItem.Home.tabId ->
|
||||
HomeScreen(
|
||||
@@ -60,6 +62,7 @@ fun NavGraphNavigationItem(
|
||||
screenOverlayVM = screenOverlayVM,
|
||||
homeVM = homeVM,
|
||||
nudgeState = nudgeState,
|
||||
uiController = uiController,
|
||||
)
|
||||
NavigationItem.Investment.tabId ->
|
||||
InvestmentsScreen(
|
||||
@@ -74,8 +77,10 @@ fun NavGraphNavigationItem(
|
||||
bottomNavBarVM = bottomNavBarVM,
|
||||
paymentManager = paymentManager,
|
||||
dashboardSharedVM = dashboardSharedVM,
|
||||
uiController = uiController,
|
||||
)
|
||||
NavigationItem.Loan.tabId -> LoansTabScreen(activity = activity)
|
||||
NavigationItem.Loan.tabId ->
|
||||
LoansTabScreen(activity = activity, uiController = uiController)
|
||||
NavigationItem.Insurance.tabId -> {
|
||||
InsuranceTabScreen(
|
||||
activity = activity,
|
||||
@@ -84,6 +89,7 @@ fun NavGraphNavigationItem(
|
||||
.padding(bottom = 56.dp)
|
||||
.statusBarsPadding()
|
||||
.background(Color.White),
|
||||
uiController = uiController,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
@@ -45,6 +46,7 @@ import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.semantics.testTagsAsResourceId
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.airbnb.lottie.compose.LottieAnimation
|
||||
import com.airbnb.lottie.compose.LottieCompositionSpec
|
||||
@@ -52,6 +54,7 @@ import com.airbnb.lottie.compose.LottieConstants
|
||||
import com.airbnb.lottie.compose.rememberLottieComposition
|
||||
import com.navi.common.alchemist.model.AlchemistWidgetModelDefinition
|
||||
import com.navi.common.alchemist.model.WidgetRenderState
|
||||
import com.navi.common.model.common.MastheadWidgetData
|
||||
import com.navi.naviwidgets.R
|
||||
import com.navi.pay.utils.conditional
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
@@ -74,6 +77,9 @@ fun FrontLayerContent(
|
||||
onEvent: (event: HpEvents) -> Unit,
|
||||
onEffect: (effect: HpEffects) -> Unit,
|
||||
staticNudgeContainer: @Composable () -> Unit,
|
||||
mastheadWidget: MastheadWidgetData? = null,
|
||||
isMastheadEnabled: Boolean,
|
||||
appBarHeight: Dp,
|
||||
) {
|
||||
CompositionLocalProvider(LocalOverscrollConfiguration provides null) {
|
||||
Column(
|
||||
@@ -85,7 +91,11 @@ fun FrontLayerContent(
|
||||
) {
|
||||
if (!widgets.isNullOrEmpty()) {
|
||||
Column {
|
||||
TopNotchUI()
|
||||
if (isMastheadEnabled) {
|
||||
MastheadWidget(homeWidgetRenderer, mastheadWidget, appBarHeight)
|
||||
} else {
|
||||
TopNotchUI()
|
||||
}
|
||||
staticNudgeContainer()
|
||||
RenderUiTronContent(
|
||||
elementList = widgets,
|
||||
@@ -108,6 +118,29 @@ fun FrontLayerContent(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MastheadWidget(
|
||||
homeWidgetRenderer: @Composable (UiTronResponse?) -> Unit,
|
||||
mastheadWidget: MastheadWidgetData?,
|
||||
appBarHeight: Dp,
|
||||
) {
|
||||
mastheadWidget?.let {
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.height(IntrinsicSize.Max)
|
||||
.padding(bottom = it.widgetBottomPadding.dp)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Box(modifier = Modifier.matchParentSize()) {
|
||||
homeWidgetRenderer(it.backgroundIllustration?.uiTronResponse)
|
||||
}
|
||||
Box(modifier = Modifier.padding(top = appBarHeight).fillMaxWidth()) {
|
||||
homeWidgetRenderer(it.widgetData?.uiTronResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TopNotchUI() {
|
||||
Column(
|
||||
@@ -185,7 +218,7 @@ private fun AnimatedContainerForWidgets(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderUiTronContent(
|
||||
internal fun RenderUiTronContent(
|
||||
elementList: List<AlchemistWidgetModelDefinition<UiTronResponse>>,
|
||||
homeWidgetRenderer: @Composable (UiTronResponse?) -> Unit,
|
||||
homeVM: () -> HomeViewModel,
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.naviapp.utils.Constants.HOME_SCREEN_IN_CAPS
|
||||
|
||||
@Composable
|
||||
fun HomeAppUpdateWidget(
|
||||
modifier: Modifier = Modifier,
|
||||
content: AlchemistWidgetModelDefinition<UiTronResponse>,
|
||||
appUpdateState: AppUpdateState,
|
||||
inAppUpdateBridge: InAppUpdateBridge,
|
||||
@@ -93,7 +94,8 @@ fun HomeAppUpdateWidget(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp)
|
||||
.border(
|
||||
width = 1.dp,
|
||||
|
||||
@@ -52,6 +52,7 @@ import com.naviapp.utils.Constants.HOME_SCREEN_IN_CAPS
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
fun HomeNotifyMeWidget(
|
||||
modifier: Modifier = Modifier,
|
||||
widget: AlchemistWidgetModelDefinition<UiTronResponse>,
|
||||
showBottomSheet: () -> Unit,
|
||||
onDismissNudge: () -> Unit,
|
||||
@@ -87,6 +88,7 @@ fun HomeNotifyMeWidget(
|
||||
if (visible) {
|
||||
notifyMeAnalytics.notifyMeNudgeViewEvent()
|
||||
NotifyMeUI(
|
||||
modifier = modifier,
|
||||
permissionGranted = (pushNotificationPermission.allPermissionsGranted),
|
||||
widgetData,
|
||||
onDismissNudge = {
|
||||
@@ -107,6 +109,7 @@ fun HomeNotifyMeWidget(
|
||||
|
||||
@Composable
|
||||
private fun NotifyMeUI(
|
||||
modifier: Modifier,
|
||||
permissionGranted: Boolean,
|
||||
widgetData: NotifyMeWidgetData?,
|
||||
onDismissNudge: () -> Unit,
|
||||
@@ -116,7 +119,8 @@ private fun NotifyMeUI(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp)
|
||||
.border(width = 1.dp, color = Color(0xFFE3E5E5), shape = RoundedCornerShape(4.dp))
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
|
||||
@@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -27,11 +28,15 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.accompanist.systemuicontroller.SystemUiController
|
||||
import com.navi.common.alchemist.model.AlchemistCollapsingToolbar
|
||||
import com.navi.common.extensions.conditional
|
||||
import com.navi.naviwidgets.R as WidgetR
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
import com.naviapp.R
|
||||
import com.naviapp.home.compose.extension.bottomShadow
|
||||
import com.naviapp.home.reducer.HpEffects
|
||||
import com.naviapp.utils.Constants.HomePageConstants.SCROLL_THRESHOLD
|
||||
|
||||
@Composable
|
||||
fun HomeTopBar(
|
||||
@@ -55,15 +60,132 @@ fun HomeTopBar(
|
||||
}
|
||||
|
||||
// Render the top bar
|
||||
Row(modifier = topBarModifier, verticalAlignment = Alignment.Top) {
|
||||
ToolbarRender(topBarModifier, statusBarHeight, topBarContent, homeWidgetRenderer)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MastheadTopBar(
|
||||
modifier: Modifier,
|
||||
statusBarHeight: Dp,
|
||||
toolbarConfig: AlchemistCollapsingToolbar?,
|
||||
renderWidget: @Composable (UiTronResponse) -> Unit,
|
||||
scrollStateProvider: () -> ScrollState,
|
||||
onEffect: (effect: HpEffects) -> Unit,
|
||||
uiController: SystemUiController,
|
||||
) {
|
||||
val scrollState by remember {
|
||||
derivedStateOf {
|
||||
val scrollOffset = scrollStateProvider().value.toFloat()
|
||||
val isScrolledBeyondThreshold = scrollOffset >= SCROLL_THRESHOLD
|
||||
val scrollProgress = (scrollOffset / SCROLL_THRESHOLD).coerceIn(0f, 1f)
|
||||
isScrolledBeyondThreshold to scrollProgress
|
||||
}
|
||||
}
|
||||
val (isScrolledBeyondThreshold, scrollProgress) = scrollState
|
||||
|
||||
// Update status bar color based on scroll
|
||||
HandleStatusBarIcons(
|
||||
uiController = uiController,
|
||||
isScrolledBeyondThreshold = isScrolledBeyondThreshold,
|
||||
toolbarConfig = toolbarConfig,
|
||||
)
|
||||
// Update icon background alpha based on scroll progress
|
||||
HandleToolbarIconsBackground(
|
||||
scrollProgress = scrollProgress,
|
||||
toolbarConfig = toolbarConfig,
|
||||
onEffect = onEffect,
|
||||
)
|
||||
// Create toolbar modifier with scroll progress
|
||||
val toolbarModifier = modifier.createToolbarModifier(scrollProgress = scrollProgress)
|
||||
|
||||
// Render the toolbar
|
||||
ToolbarRender(
|
||||
modifier = toolbarModifier,
|
||||
statusBarHeight = statusBarHeight,
|
||||
toolbarContent = toolbarConfig?.toolBarNav?.uiTronResponse,
|
||||
homeWidgetRenderer = renderWidget,
|
||||
mastheadEnable = true,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Modifier.createToolbarModifier(scrollProgress: Float): Modifier =
|
||||
remember(scrollProgress) {
|
||||
bottomShadow(showShadow = scrollProgress > 0, elevation = 5f, shadowLengthFactor = 8)
|
||||
.drawBehind { drawRect(color = Color.White.copy(alpha = scrollProgress)) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes status bar icon color based on background color and scroll state. Uses dark icons for
|
||||
* light backgrounds.
|
||||
*/
|
||||
@Composable
|
||||
private fun HandleStatusBarIcons(
|
||||
uiController: SystemUiController,
|
||||
isScrolledBeyondThreshold: Boolean,
|
||||
toolbarConfig: AlchemistCollapsingToolbar?,
|
||||
) {
|
||||
LaunchedEffect(
|
||||
key1 = isScrolledBeyondThreshold,
|
||||
key2 = toolbarConfig?.mastheadWidget?.useLightStatusBar,
|
||||
) {
|
||||
toolbarConfig?.mastheadWidget?.let { mastheadWidget ->
|
||||
when {
|
||||
mastheadWidget.useLightStatusBar -> {
|
||||
uiController.setStatusBarColor(
|
||||
color = Color.Transparent,
|
||||
darkIcons = isScrolledBeyondThreshold,
|
||||
)
|
||||
}
|
||||
|
||||
!uiController.statusBarDarkContentEnabled -> {
|
||||
uiController.setStatusBarColor(color = Color.Transparent, darkIcons = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the masthead icons' background alpha based on scroll progress. Ensures a minimum alpha of
|
||||
* 0.3 (factor 3) and a maximum of 1.0 (factor 10).
|
||||
*/
|
||||
@Composable
|
||||
private fun HandleToolbarIconsBackground(
|
||||
scrollProgress: Float,
|
||||
toolbarConfig: AlchemistCollapsingToolbar?,
|
||||
onEffect: (HpEffects) -> Unit,
|
||||
) {
|
||||
val iconBackgroundAlphaFactor = remember(scrollProgress) { ((scrollProgress * 7) + 3).toInt() }
|
||||
|
||||
LaunchedEffect(
|
||||
key1 = iconBackgroundAlphaFactor,
|
||||
key2 = toolbarConfig?.mastheadWidget?.updateIconsOnScroll,
|
||||
) {
|
||||
toolbarConfig
|
||||
?.mastheadWidget
|
||||
?.takeIf { it.updateIconsOnScroll }
|
||||
?.let { onEffect(HpEffects.UpdateMastheadIconsState(iconBackgroundAlphaFactor)) }
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ToolbarRender(
|
||||
modifier: Modifier,
|
||||
statusBarHeight: Dp,
|
||||
toolbarContent: UiTronResponse?,
|
||||
homeWidgetRenderer: @Composable (UiTronResponse) -> Unit,
|
||||
mastheadEnable: Boolean = false,
|
||||
) {
|
||||
Row(modifier = modifier, verticalAlignment = Alignment.Top) {
|
||||
Row(Modifier.padding(top = statusBarHeight)) {
|
||||
topBarContent?.let { homeWidgetRenderer(it) } ?: DefaultTopBar()
|
||||
toolbarContent?.let { homeWidgetRenderer(it) } ?: DefaultTopBar(mastheadEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DefaultTopBar() {
|
||||
fun DefaultTopBar(mastheadEnable: Boolean = false) {
|
||||
Row(
|
||||
Modifier.fillMaxWidth().height(60.dp).padding(start = 16.dp, end = 16.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
@@ -71,12 +193,18 @@ fun DefaultTopBar() {
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(40.dp),
|
||||
painter = painterResource(id = R.drawable.app_ic_profile),
|
||||
painter =
|
||||
if (mastheadEnable)
|
||||
painterResource(id = com.navi.naviwidgets.R.drawable.ic_profile_with_upi)
|
||||
else painterResource(id = R.drawable.app_ic_profile),
|
||||
contentDescription = "Profile Icon",
|
||||
)
|
||||
Image(
|
||||
modifier = Modifier.size(40.dp),
|
||||
painter = painterResource(id = WidgetR.drawable.navi_widgets_ic_notification),
|
||||
painter =
|
||||
if (mastheadEnable)
|
||||
painterResource(id = com.navi.naviwidgets.R.drawable.ic_home_notification)
|
||||
else painterResource(id = WidgetR.drawable.navi_widgets_ic_notification),
|
||||
contentDescription = "Notifications Icon",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,11 +7,15 @@
|
||||
|
||||
package com.naviapp.home.compose.home.ui.screen
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.google.accompanist.systemuicontroller.SystemUiController
|
||||
import com.navi.common.checkmate.core.CheckMateManager
|
||||
import com.navi.common.checkmate.model.MetricInfo
|
||||
import com.navi.common.network.models.RepoResult
|
||||
@@ -46,6 +50,7 @@ fun HomeScreen(
|
||||
naviAnalyticsEventTracker: NaviAnalytics.Home,
|
||||
screenOverlayVM: ScreenOverlayVM,
|
||||
nudgeState: () -> NudgeState,
|
||||
uiController: SystemUiController,
|
||||
) {
|
||||
val homeScrollState = rememberScrollState()
|
||||
val appUpdateState by sharedVM.appUpdateState.collectAsStateWithLifecycle()
|
||||
@@ -119,6 +124,7 @@ fun HomeScreen(
|
||||
},
|
||||
)
|
||||
},
|
||||
uiController = uiController,
|
||||
)
|
||||
} else {
|
||||
HomeScreenScaffoldRoot(
|
||||
@@ -138,6 +144,10 @@ fun HomeScreen(
|
||||
state = nudgeState().staticNudgeData,
|
||||
widgetRenderer = {
|
||||
WidgetRenderer(
|
||||
modifier =
|
||||
if (hpStates().collapsingToolbar?.mastheadEnable == true)
|
||||
Modifier.padding(top = 8.dp)
|
||||
else Modifier,
|
||||
staticNudgeData = nudgeState().staticNudgeData,
|
||||
sharedVM = sharedVM,
|
||||
viewModel = screenOverlayVM,
|
||||
@@ -154,6 +164,7 @@ fun HomeScreen(
|
||||
},
|
||||
)
|
||||
},
|
||||
uiController = uiController,
|
||||
)
|
||||
hpStates().footer?.let { handleBottomBarData(it, sharedVM) }
|
||||
}
|
||||
|
||||
@@ -32,11 +32,13 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import com.google.accompanist.systemuicontroller.SystemUiController
|
||||
import com.navi.common.utils.getStatusBarHeight
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
import com.naviapp.home.compose.home.ui.content.BackLayerContent
|
||||
import com.naviapp.home.compose.home.ui.content.FrontLayerContent
|
||||
import com.naviapp.home.compose.home.ui.header.HomeTopBar
|
||||
import com.naviapp.home.compose.home.ui.header.MastheadTopBar
|
||||
import com.naviapp.home.compose.home.utils.TopNaviMiddlePillAnimation
|
||||
import com.naviapp.home.compose.home.utils.backDropNestedScrollConnection
|
||||
import com.naviapp.home.compose.home.utils.getFrontLayerOffset
|
||||
@@ -56,6 +58,7 @@ internal fun HomeScreenScaffoldRoot(
|
||||
homeVM: () -> HomeViewModel,
|
||||
homeWidgetRenderer: @Composable (UiTronResponse?) -> Unit,
|
||||
staticNudgeContainer: @Composable () -> Unit,
|
||||
uiController: SystemUiController,
|
||||
) {
|
||||
val density = LocalDensity.current
|
||||
val statusBarHeight = remember { with(density) { getStatusBarHeight().toDp() } }
|
||||
@@ -64,39 +67,63 @@ internal fun HomeScreenScaffoldRoot(
|
||||
val frontLayerShape = remember {
|
||||
RoundedCornerShape(topStart = HOME_SHAPE_CURVATURE, topEnd = HOME_SHAPE_CURVATURE)
|
||||
}
|
||||
|
||||
Box(Modifier.fillMaxSize().navigationBarsPadding()) {
|
||||
BackLayerContent(
|
||||
backLayerHeight = backLayerHeight,
|
||||
homeWidgetRenderer = homeWidgetRenderer,
|
||||
backLayerData = (hpStates().collapsingToolbar?.collapsingTopNav)?.uiTronResponse,
|
||||
)
|
||||
|
||||
FrontLayerRoot(
|
||||
hpStates = hpStates,
|
||||
homeScrollState = homeScrollState,
|
||||
homeVM = homeVM,
|
||||
homeWidgetRenderer = homeWidgetRenderer,
|
||||
frontLayerShape = frontLayerShape,
|
||||
appBarHeight = appBarHeight,
|
||||
backLayerHeight = backLayerHeight,
|
||||
staticNudgeContainer = staticNudgeContainer,
|
||||
)
|
||||
|
||||
HomeTopBar(
|
||||
modifier = Modifier.align(Alignment.TopCenter),
|
||||
appBarHeight = appBarHeight,
|
||||
statusBarHeight = statusBarHeight,
|
||||
topBarContent = (hpStates().collapsingToolbar?.toolBarNav)?.uiTronResponse,
|
||||
homeWidgetRenderer = homeWidgetRenderer,
|
||||
homeScrollState = homeScrollState,
|
||||
)
|
||||
if (hpStates().collapsingToolbar?.mastheadEnable == true) {
|
||||
FrontLayerContent(
|
||||
modifier = Modifier,
|
||||
widgets = (hpStates().frontLayerContent),
|
||||
frontLayerShape = frontLayerShape,
|
||||
homeScrollState = homeScrollState,
|
||||
homeVM = homeVM,
|
||||
homeWidgetRenderer = homeWidgetRenderer,
|
||||
onEffect = { homeVM().setEffect { it } },
|
||||
onEvent = { homeVM().sendEvent(it) },
|
||||
isRenderingFirstTime = hpStates().isRenderingFirstTime,
|
||||
staticNudgeContainer = staticNudgeContainer,
|
||||
mastheadWidget = (hpStates().collapsingToolbar?.mastheadWidget),
|
||||
isMastheadEnabled = true,
|
||||
appBarHeight = appBarHeight,
|
||||
)
|
||||
MastheadTopBar(
|
||||
modifier = Modifier,
|
||||
statusBarHeight = statusBarHeight,
|
||||
toolbarConfig = (hpStates().collapsingToolbar),
|
||||
renderWidget = homeWidgetRenderer,
|
||||
scrollStateProvider = homeScrollState,
|
||||
onEffect = { homeVM().setEffect { it } },
|
||||
uiController = uiController,
|
||||
)
|
||||
} else {
|
||||
BackLayerContent(
|
||||
backLayerHeight = backLayerHeight,
|
||||
homeWidgetRenderer = homeWidgetRenderer,
|
||||
backLayerData = (hpStates().collapsingToolbar?.collapsingTopNav)?.uiTronResponse,
|
||||
)
|
||||
FrontLayerWithBackDropScroll(
|
||||
hpStates = hpStates,
|
||||
homeScrollState = homeScrollState,
|
||||
homeVM = homeVM,
|
||||
homeWidgetRenderer = homeWidgetRenderer,
|
||||
frontLayerShape = frontLayerShape,
|
||||
appBarHeight = appBarHeight,
|
||||
backLayerHeight = backLayerHeight,
|
||||
staticNudgeContainer = staticNudgeContainer,
|
||||
)
|
||||
HomeTopBar(
|
||||
modifier = Modifier.align(Alignment.TopCenter),
|
||||
appBarHeight = appBarHeight,
|
||||
statusBarHeight = statusBarHeight,
|
||||
topBarContent = (hpStates().collapsingToolbar?.toolBarNav)?.uiTronResponse,
|
||||
homeWidgetRenderer = homeWidgetRenderer,
|
||||
homeScrollState = homeScrollState,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun FrontLayerRoot(
|
||||
private fun FrontLayerWithBackDropScroll(
|
||||
hpStates: () -> HpStates,
|
||||
homeScrollState: () -> ScrollState,
|
||||
homeVM: () -> HomeViewModel,
|
||||
@@ -137,15 +164,17 @@ private fun FrontLayerRoot(
|
||||
.nestedScroll(backDropNestedScrollConnection(draggableState))
|
||||
.anchoredDraggable(state = draggableState, orientation = Orientation.Vertical)
|
||||
.padding(bottom = appBarHeight),
|
||||
widgets = (hpStates().frontLayerContent),
|
||||
frontLayerShape = frontLayerShape,
|
||||
widgets = (hpStates().frontLayerContent),
|
||||
homeWidgetRenderer = homeWidgetRenderer,
|
||||
isRenderingFirstTime = hpStates().isRenderingFirstTime,
|
||||
homeScrollState = homeScrollState,
|
||||
homeVM = homeVM,
|
||||
homeWidgetRenderer = homeWidgetRenderer,
|
||||
onEffect = { homeVM().setEffect { it } },
|
||||
onEvent = { homeVM().sendEvent(it) },
|
||||
isRenderingFirstTime = hpStates().isRenderingFirstTime,
|
||||
onEffect = { homeVM().setEffect { it } },
|
||||
staticNudgeContainer = staticNudgeContainer,
|
||||
isMastheadEnabled = false,
|
||||
appBarHeight = appBarHeight,
|
||||
)
|
||||
|
||||
LaunchedEffect(draggableState.settledValue) {
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.google.accompanist.systemuicontroller.SystemUiController
|
||||
import com.navi.base.model.NaviClickAction
|
||||
import com.navi.common.utils.setStatusBarColorInt
|
||||
import com.navi.design.utils.parseColorSafe
|
||||
import com.navi.common.utils.parseColor
|
||||
import com.navi.naviwidgets.callbacks.WidgetCallback
|
||||
import com.naviapp.common.tab.InsuranceTabViewModel
|
||||
import com.naviapp.home.compose.activity.HomePageActivity
|
||||
@@ -19,7 +19,11 @@ import com.naviapp.home.dashboard.ui.compose.insuranceTab.InsuranceTabInit
|
||||
import com.naviapp.home.dashboard.ui.compose.insuranceTab.RenderUiTronDataSecondary
|
||||
|
||||
@Composable
|
||||
fun InsuranceTabScreen(activity: HomePageActivity, modifier: Modifier = Modifier) {
|
||||
fun InsuranceTabScreen(
|
||||
activity: HomePageActivity,
|
||||
modifier: Modifier = Modifier,
|
||||
uiController: SystemUiController,
|
||||
) {
|
||||
val viewModel: InsuranceTabViewModel = hiltViewModel()
|
||||
val widgetCallback =
|
||||
object : WidgetCallback {
|
||||
@@ -32,10 +36,10 @@ fun InsuranceTabScreen(activity: HomePageActivity, modifier: Modifier = Modifier
|
||||
modifier = modifier,
|
||||
viewModel = viewModel,
|
||||
widgetCallback = widgetCallback,
|
||||
toggleStatusBarColor = { color -> toggleStatusBarColor(activity, color) },
|
||||
toggleStatusBarColor = { color -> toggleStatusBarColor(uiController, color) },
|
||||
)
|
||||
}
|
||||
|
||||
private fun toggleStatusBarColor(activity: Activity, color: String) {
|
||||
activity.setStatusBarColorInt(color.parseColorSafe())
|
||||
private fun toggleStatusBarColor(uiController: SystemUiController, color: String) {
|
||||
uiController.setStatusBarColor(color = Color(color.parseColor()), darkIcons = true)
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.google.accompanist.systemuicontroller.SystemUiController
|
||||
import com.navi.common.model.ModuleNameV2
|
||||
import com.navi.common.ui.errorview.FullScreenErrorComposeView
|
||||
import com.navi.common.utils.setStatusBarColorInt
|
||||
import com.navi.design.utils.parseColorSafe
|
||||
import com.navi.common.utils.parseColor
|
||||
import com.navi.paymentclients.viewmodel.base.PaymentManager
|
||||
import com.naviapp.common.viewmodel.BottomNavBarVM
|
||||
import com.naviapp.dashboard.viewmodels.DashboardSharedVM
|
||||
@@ -38,6 +38,7 @@ fun InvestmentsScreen(
|
||||
bottomNavBarVM: BottomNavBarVM,
|
||||
paymentManager: PaymentManager,
|
||||
dashboardSharedVM: DashboardSharedVM,
|
||||
uiController: SystemUiController,
|
||||
) {
|
||||
val investmentsTabVm by lazy { ViewModelProvider(activity)[InvestmentsVm::class.java] }
|
||||
val investmentsScreenData =
|
||||
@@ -61,6 +62,7 @@ fun InvestmentsScreen(
|
||||
)
|
||||
InvestmentsTabShimmer()
|
||||
}
|
||||
|
||||
is InvestmentsVm.InvestmentsTabScreenState.Success -> {
|
||||
investmentsTabVm.fireEvent(
|
||||
eventName = InvestmentTabEvents.INVESTMENT_TAB_SUCCESS.eventName,
|
||||
@@ -73,7 +75,7 @@ fun InvestmentsScreen(
|
||||
sharedVM = sharedVM,
|
||||
investmentsScreenHelper = investmentsScreenHelper,
|
||||
hopper = hopper,
|
||||
toggleStatusBarColor = { toggleStatusBarColor(activity, it) },
|
||||
toggleStatusBarColor = { toggleStatusBarColor(uiController, it) },
|
||||
bottomNavBarVM = bottomNavBarVM,
|
||||
paymentManager = paymentManager,
|
||||
dashboardSharedVM = dashboardSharedVM,
|
||||
@@ -84,6 +86,7 @@ fun InvestmentsScreen(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is InvestmentsVm.InvestmentsTabScreenState.Error -> {
|
||||
FullScreenErrorComposeView(
|
||||
error = investmentsScreenData.error,
|
||||
@@ -98,6 +101,6 @@ fun InvestmentsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleStatusBarColor(activity: Activity, color: String) {
|
||||
activity.setStatusBarColorInt(color.parseColorSafe())
|
||||
private fun toggleStatusBarColor(uiController: SystemUiController, color: String) {
|
||||
uiController.setStatusBarColor(color = Color(color.parseColor()), darkIcons = true)
|
||||
}
|
||||
|
||||
@@ -15,9 +15,11 @@ import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.accompanist.systemuicontroller.SystemUiController
|
||||
import com.navi.analytics.utils.NaviTrackEvent
|
||||
import com.navi.common.ui.errorview.FullScreenErrorComposeView
|
||||
import com.navi.common.utils.Constants.CTAData
|
||||
@@ -33,7 +35,14 @@ import com.naviapp.utils.Constants.PL_WEB_URL_HOST_NAME
|
||||
import com.naviapp.utils.Constants.STATE
|
||||
|
||||
@Composable
|
||||
fun LoansTabScreen(activity: HomePageActivity, loansTabVm: LoanTabVm = hiltViewModel()) {
|
||||
fun LoansTabScreen(
|
||||
activity: HomePageActivity,
|
||||
loansTabVm: LoanTabVm = hiltViewModel(),
|
||||
uiController: SystemUiController,
|
||||
) {
|
||||
LaunchedEffect(Unit) {
|
||||
uiController.setStatusBarColor(color = Color.Transparent, darkIcons = true)
|
||||
}
|
||||
val loansTabHelper by lazy { LoansTabHelper() }
|
||||
LoansTabWebView(loansTabVm, activity, loansTabHelper)
|
||||
}
|
||||
@@ -57,6 +66,7 @@ private fun LoansTabWebView(
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
is AuthTokenState.Success -> {
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
RenderWebView(
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2023-2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.naviapp.home.model
|
||||
|
||||
import com.navi.common.alchemist.model.AlchemistCollapsingToolbar
|
||||
import com.navi.common.alchemist.model.AlchemistWidgetModelDefinition
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
|
||||
data class HomePrioritySectionData(
|
||||
val content: List<AlchemistWidgetModelDefinition<UiTronResponse>>?,
|
||||
val topNav: AlchemistCollapsingToolbar? = null,
|
||||
)
|
||||
@@ -28,6 +28,7 @@ import com.naviapp.common.model.UiTronActionHandler
|
||||
import com.naviapp.home.compose.home.utils.updateScreenContent
|
||||
import com.naviapp.home.compose.model.CtaActionEvent
|
||||
import com.naviapp.home.compose.model.InitiatePaymentFromComposeData
|
||||
import com.naviapp.home.model.HomePrioritySectionData
|
||||
import com.naviapp.models.response.HomeFeatureResponse
|
||||
|
||||
class HomeReducer : BaseReducer<HpStates, HpEvents> {
|
||||
@@ -51,7 +52,20 @@ class HomeReducer : BaseReducer<HpStates, HpEvents> {
|
||||
bottomSheets = it.bottomSheets,
|
||||
systemBackCta = it.systemBackCta,
|
||||
renderActions = it.renderActions,
|
||||
collapsingToolbar = it.collapsingToolbar,
|
||||
collapsingToolbar = it.collapsingToolbar ?: previousState.collapsingToolbar,
|
||||
screenMetaData = event.content.screenMetaData,
|
||||
)
|
||||
} ?: previousState.copy(screenMetaData = event.content.screenMetaData)
|
||||
}
|
||||
|
||||
is HpEvents.UpdateScreenWithoutContentAndTopNav -> {
|
||||
event.content.screenStructure?.let {
|
||||
previousState.copy(
|
||||
header = it.header,
|
||||
footer = it.footer,
|
||||
bottomSheets = it.bottomSheets,
|
||||
systemBackCta = it.systemBackCta,
|
||||
renderActions = it.renderActions,
|
||||
screenMetaData = event.content.screenMetaData,
|
||||
)
|
||||
} ?: previousState.copy(screenMetaData = event.content.screenMetaData)
|
||||
@@ -83,6 +97,22 @@ class HomeReducer : BaseReducer<HpStates, HpEvents> {
|
||||
frontLayerContent = updatedList,
|
||||
)
|
||||
}
|
||||
is HpEvents.UpdatePrioritySectionData -> {
|
||||
val updatedList =
|
||||
updateScreenContent(
|
||||
renderingFirstTime = previousState.isRenderingFirstTime,
|
||||
newWidgets =
|
||||
event.prioritySectionData.content ?: previousState.frontLayerContent,
|
||||
oldWidgets = previousState.frontLayerContent,
|
||||
)
|
||||
previousState.copy(
|
||||
isLoading = false,
|
||||
isError = false,
|
||||
frontLayerContent = updatedList,
|
||||
collapsingToolbar =
|
||||
event.prioritySectionData.topNav ?: previousState.collapsingToolbar,
|
||||
)
|
||||
}
|
||||
is HpEvents.RenderedFirstTime -> {
|
||||
previousState.copy(isRenderingFirstTime = false)
|
||||
}
|
||||
@@ -116,6 +146,9 @@ sealed interface HpEvents : UiEvent {
|
||||
|
||||
data class UpdateScreenWithoutContent(val content: AlchemistScreenDefinition) : HpEvents
|
||||
|
||||
data class UpdateScreenWithoutContentAndTopNav(val content: AlchemistScreenDefinition) :
|
||||
HpEvents
|
||||
|
||||
data class UpdateShadowOnFrontLayer(val showShadowOnFrontLayer: Boolean) : HpEvents
|
||||
|
||||
data class UpdateScreenContentWidgetRenderState(val id: String, val state: WidgetRenderState) :
|
||||
@@ -127,6 +160,9 @@ sealed interface HpEvents : UiEvent {
|
||||
val content: List<AlchemistWidgetModelDefinition<UiTronResponse>>
|
||||
) : HpEvents
|
||||
|
||||
data class UpdatePrioritySectionData(val prioritySectionData: HomePrioritySectionData) :
|
||||
HpEvents
|
||||
|
||||
data object ShowProfile : HpEvents
|
||||
|
||||
data class UpdateProfileDrawerState(val state: Boolean) : HpEvents
|
||||
@@ -190,4 +226,6 @@ sealed interface HpEffects : UiEffect {
|
||||
data object HomePageUiRenderedEvent : HpEffects
|
||||
|
||||
data object TopNavRevealedAnalytics : HpEffects
|
||||
|
||||
data class UpdateMastheadIconsState(val alphaFactor: Int) : HpEffects
|
||||
}
|
||||
|
||||
@@ -9,10 +9,12 @@ package com.naviapp.home.usecase
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.navi.common.alchemist.model.AlchemistCollapsingToolbar
|
||||
import com.navi.common.alchemist.model.AlchemistScreenDefinition
|
||||
import com.navi.common.alchemist.model.AlchemistWidgetModelDefinition
|
||||
import com.navi.common.utils.log
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
import com.naviapp.home.model.HomePrioritySectionData
|
||||
import com.naviapp.network.di.DataDeserializers
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -25,12 +27,18 @@ class AsyncDeserialization @Inject constructor(@DataDeserializers private val de
|
||||
object : TypeToken<AlchemistWidgetModelDefinition<UiTronResponse>>() {}.type
|
||||
|
||||
private var contentArray: JSONArray? = null
|
||||
private var topNav: JSONObject? = null
|
||||
private var cacheEntity: String? = null
|
||||
private var isTopNavInPrioritySection: Boolean = false
|
||||
|
||||
fun setCacheEntity(newCacheEntity: String) {
|
||||
if (cacheEntity != newCacheEntity) {
|
||||
cacheEntity = newCacheEntity
|
||||
contentArray = extractFrontLayerJsonArray(cacheEntity)
|
||||
extractTopNavDataAndMastheadStatus(cacheEntity).let { (nav, isMastheadEnabled) ->
|
||||
topNav = nav
|
||||
isTopNavInPrioritySection = isMastheadEnabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,9 +48,14 @@ class AsyncDeserialization @Inject constructor(@DataDeserializers private val de
|
||||
return getContentInRange(startIndex, endIndex)
|
||||
}
|
||||
|
||||
suspend fun getPrioritySection(): List<AlchemistWidgetModelDefinition<UiTronResponse>>? {
|
||||
val endIndex = CHUNK_SIZE.coerceAtMost(contentArray?.length() ?: 0)
|
||||
return getContentInRange(0, endIndex)
|
||||
suspend fun getPrioritySection(): HomePrioritySectionData {
|
||||
val contentLength = contentArray?.length() ?: 0
|
||||
val endIndex = CHUNK_SIZE.coerceAtMost(contentLength)
|
||||
val topNavData = if (isTopNavInPrioritySection) getTopNav() else null
|
||||
return HomePrioritySectionData(
|
||||
content = getContentInRange(0, endIndex),
|
||||
topNav = topNavData,
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun getScreen(cacheEntity: String): AlchemistScreenDefinition {
|
||||
@@ -51,11 +64,18 @@ class AsyncDeserialization @Inject constructor(@DataDeserializers private val de
|
||||
}
|
||||
}
|
||||
|
||||
// Here content refers to content in Alchemist screen definition
|
||||
/**
|
||||
* Here content refers to content in Alchemist screen definition. This function avoid taking the
|
||||
* priority section if masthead isEnabled. *
|
||||
*/
|
||||
suspend fun getScreenDefinitionWithoutContent(): AlchemistScreenDefinition? {
|
||||
return withContext(Dispatchers.Default) {
|
||||
val screenJson = cacheEntity?.let { JSONObject(it) }
|
||||
screenJson?.optJSONObject("screenStructure")?.remove("content")
|
||||
screenJson
|
||||
?.optJSONObject("screenStructure")
|
||||
?.takeIf { isTopNavInPrioritySection }
|
||||
?.remove("collapsingToolbar")
|
||||
val strippedScreenJson = screenJson.toString()
|
||||
deserializer.fromJson(strippedScreenJson, AlchemistScreenDefinition::class.java)
|
||||
}
|
||||
@@ -74,6 +94,12 @@ class AsyncDeserialization @Inject constructor(@DataDeserializers private val de
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getTopNav(): AlchemistCollapsingToolbar {
|
||||
return withContext(Dispatchers.Default) {
|
||||
deserializer.fromJson(topNav.toString(), AlchemistCollapsingToolbar::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractFrontLayerJsonArray(cacheEntity: String?): JSONArray? {
|
||||
return try {
|
||||
val screenJson = cacheEntity?.let { JSONObject(it) } ?: return null
|
||||
@@ -87,6 +113,24 @@ class AsyncDeserialization @Inject constructor(@DataDeserializers private val de
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractTopNavDataAndMastheadStatus(
|
||||
cacheEntity: String?
|
||||
): Pair<JSONObject?, Boolean> {
|
||||
return try {
|
||||
val screenJson =
|
||||
cacheEntity
|
||||
?.let { JSONObject(it) }
|
||||
?.optJSONObject("screenStructure")
|
||||
?.optJSONObject("collapsingToolbar")
|
||||
|
||||
val isMastheadEnabled = screenJson?.optBoolean("mastheadEnable", false) ?: false
|
||||
Pair(screenJson, isMastheadEnabled)
|
||||
} catch (e: Exception) {
|
||||
e.log()
|
||||
Pair(null, false)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CHUNK_SIZE = 4
|
||||
}
|
||||
|
||||
@@ -134,6 +134,7 @@ fun HandleUitronRenderer(uiTronResponse: UiTronResponse?, viewModel: BaseVM) {
|
||||
|
||||
@Composable
|
||||
fun WidgetRenderer(
|
||||
modifier: Modifier = Modifier,
|
||||
staticNudgeData: StaticNudgeData?,
|
||||
sharedVM: SharedVM,
|
||||
viewModel: ScreenOverlayVM,
|
||||
@@ -147,6 +148,7 @@ fun WidgetRenderer(
|
||||
when (widget.widgetName) {
|
||||
HomeCustomWidgetType.AppUpdateNudge.value -> {
|
||||
HomeAppUpdateWidget(
|
||||
modifier = modifier,
|
||||
content = widget,
|
||||
appUpdateState = appUpdateState(),
|
||||
inAppUpdateBridge = inAppUpdateBridge,
|
||||
@@ -165,6 +167,7 @@ fun WidgetRenderer(
|
||||
}
|
||||
HomeCustomWidgetType.NotifyMeWidget.value -> {
|
||||
HomeNotifyMeWidget(
|
||||
modifier = modifier,
|
||||
widget = widget,
|
||||
showBottomSheet = {
|
||||
sharedVM.updateBottomSheetState(
|
||||
|
||||
@@ -262,9 +262,7 @@ constructor(
|
||||
deserializer.setCacheEntity(data.value)
|
||||
viewModelScope
|
||||
.async {
|
||||
deserializer.getPrioritySection()?.let {
|
||||
sendEvent(HpEvents.UpdateFrontLayerContent(it))
|
||||
}
|
||||
sendEvent(HpEvents.UpdatePrioritySectionData(deserializer.getPrioritySection()))
|
||||
}
|
||||
.await()
|
||||
viewModelScope
|
||||
|
||||
@@ -270,6 +270,9 @@ object Constants {
|
||||
val DRAG_POSITIONAL_THRESHOLD = 56.dp
|
||||
val DRAG_VELOCITY_THRESHOLD = 125.dp
|
||||
const val SCROLL_FADE = "scroll_fade"
|
||||
const val SCROLL_THRESHOLD = 60f
|
||||
const val TOP_NAV_ARC_BACKGROUND = "top_nav_arc_background"
|
||||
const val ALPHA = "alpha_"
|
||||
}
|
||||
|
||||
// Home Custom Widget Constants
|
||||
|
||||
@@ -9,6 +9,7 @@ package com.navi.common.alchemist.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.common.model.common.CollapsingTopNavConfig
|
||||
import com.navi.common.model.common.MastheadWidgetData
|
||||
import com.navi.common.model.common.UiTronActionAndResponse
|
||||
import com.navi.common.utils.Constants.DEFAULT_BACKGROUND_COLOR
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
@@ -64,6 +65,8 @@ data class AlchemistFloatingActionButton(
|
||||
data class AlchemistCollapsingToolbar(
|
||||
val toolBarNav: UiTronActionAndResponse? = null,
|
||||
val collapsingTopNav: UiTronActionAndResponse? = null,
|
||||
val mastheadWidget: MastheadWidgetData? = null,
|
||||
val mastheadEnable: Boolean? = null,
|
||||
val collapsingTopNavConfig: CollapsingTopNavConfig? = null,
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.common.model.common
|
||||
|
||||
data class MastheadWidgetData(
|
||||
val widgetData: UiTronActionAndResponse? = null,
|
||||
val backgroundIllustration: UiTronActionAndResponse? = null,
|
||||
val useLightStatusBar: Boolean = false,
|
||||
val updateIconsOnScroll: Boolean = false,
|
||||
val widgetBottomPadding: Int = 16,
|
||||
)
|
||||
@@ -235,6 +235,7 @@ object NaviWidgetIconUtils {
|
||||
private const val ARROW_FORWARD_FILLED_PURPLE = "ARROW_FORWARD_FILLED_PURPLE"
|
||||
private const val ARROW_TERTIARY_BLUE = "ARROW_TERTIARY_BLUE"
|
||||
private const val PROFILE_ICON = "PROFILE_ICON"
|
||||
private const val PROFILE_ICON_WITH_UPI = "PROFILE_ICON_WITH_UPI"
|
||||
private const val YELLOW_ALERT_ICON = "YELLOW_ALERT_ICON"
|
||||
private const val NEW_GREEN_TICK_ICON_LARGE = "NEW_GREEN_TICK_ICON_LARGE"
|
||||
private const val RED_BG_CROSS_LARGE = "RED_BG_CROSS_LARGE"
|
||||
@@ -249,6 +250,7 @@ object NaviWidgetIconUtils {
|
||||
private const val EXPLORE_FUNDS_MAGNIFIER = "EXPLORE_FUNDS_MAGNIFIER"
|
||||
private const val LI_ARROW_RIGHT = "LI_ARROW_RIGHT"
|
||||
private const val IN_APP_NOTIFICATION_ICON = "IN_APP_NOTIFICATION_ICON"
|
||||
private const val NOTIFICATION_ICON_WITH_BORDER = "NOTIFICATION_ICON_WITH_BORDER"
|
||||
const val ARROW_LEFT_PURPLE = "ARROW_LEFT_PURPLE"
|
||||
const val TRIANGULAR_TIP_BLUE = "TRIANGULAR_TIP_BLUE"
|
||||
const val BULLET_ELLIPSE_GREY = "BULLET_ELLIPSE_GREY"
|
||||
@@ -560,6 +562,7 @@ object NaviWidgetIconUtils {
|
||||
ORANGE_GRADIENT_LOADER_ICON -> R.drawable.ic_orange_gradient_loader
|
||||
ARROW_TERTIARY_BLUE -> R.drawable.ic_blue_chevron_right
|
||||
PROFILE_ICON -> R.drawable.navi_widgets_ic_profile
|
||||
PROFILE_ICON_WITH_UPI -> R.drawable.ic_profile_with_upi
|
||||
YELLOW_ALERT_ICON -> R.drawable.navi_widgets_ic_yellow_alert
|
||||
WHITE_TICK_GREEN_BG_60 -> R.drawable.ic_green_tick_60
|
||||
ICON_SINGLE_SELECTED_V2 -> R.drawable.ic_single_selected_v2
|
||||
@@ -657,6 +660,7 @@ object NaviWidgetIconUtils {
|
||||
NAVI_COIN_GREY -> R.drawable.ic_navi_coin_grey
|
||||
HOLIDAY_SCRATCH_CARD_IMAGE -> R.drawable.ic_christmas_sc
|
||||
REPUBLIC_DAY_SCRATCH_CARD_IMAGE -> R.drawable.ic_republic_day_scratch_card
|
||||
NOTIFICATION_ICON_WITH_BORDER -> R.drawable.ic_home_notification
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="40dp"
|
||||
android:height="40dp"
|
||||
android:viewportWidth="40"
|
||||
android:viewportHeight="40">
|
||||
<path
|
||||
android:pathData="M20,0.556L20,0.556A19.444,19.444 0,0 1,39.444 20L39.444,20A19.444,19.444 0,0 1,20 39.444L20,39.444A19.444,19.444 0,0 1,0.556 20L0.556,20A19.444,19.444 0,0 1,20 0.556z"
|
||||
android:strokeWidth="1.11111"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#EBEBEB"/>
|
||||
<path
|
||||
android:pathData="M13.768,17.409C13.768,14.244 16.059,11.413 19.236,11.044C23.011,10.607 26.222,13.507 26.222,17.156V18.871C26.222,20.448 26.579,21.99 27.281,23.406L27.926,24.73C28.363,25.616 27.707,26.663 26.705,26.663H13.308C12.307,26.663 11.639,25.616 12.088,24.73L12.732,23.406C13.423,21.99 13.791,20.436 13.791,18.871V17.409H13.768Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.4"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#1F002A"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M17.278,26.653C17.474,27.988 18.614,29.001 20.006,29.001C21.399,29.001 22.527,27.988 22.722,26.653"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.4"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#1F002A"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,118 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="40dp"
|
||||
android:height="40dp"
|
||||
android:viewportWidth="40"
|
||||
android:viewportHeight="40">
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M20,0.5L20,0.5A19.5,19.5 0,0 1,39.5 20L39.5,20A19.5,19.5 0,0 1,20 39.5L20,39.5A19.5,19.5 0,0 1,0.5 20L0.5,20A19.5,19.5 0,0 1,20 0.5z"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#EBEBEB"/>
|
||||
<path
|
||||
android:pathData="M19.993,12.047C21.34,12.047 22.432,10.955 22.432,9.608C22.432,8.262 21.34,7.17 19.993,7.17C18.646,7.17 17.555,8.262 17.555,9.608C17.555,10.955 18.646,12.047 19.993,12.047Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#1F002A"/>
|
||||
<path
|
||||
android:pathData="M25.976,18.205V19.527C25.976,20.069 25.542,20.503 25,20.503H14.997C14.461,20.503 14.022,20.069 14.022,19.527V18.205C14.022,16.001 15.67,14.616 17.738,14.045C19.177,13.65 20.821,13.65 22.264,14.045C22.294,14.055 22.328,14.065 22.357,14.075C24.381,14.66 25.976,16.035 25.976,18.205Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="1.2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#1F002A"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M8.779,24.111h21.859v7.715h-21.859z"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M6.952,21.594H32.472V34.342H6.952V21.594Z"/>
|
||||
<path
|
||||
android:pathData="M8.958,30.738H9.122L8.97,31.373C8.947,31.467 8.951,31.538 8.983,31.585C9.014,31.632 9.071,31.656 9.156,31.656C9.24,31.656 9.309,31.632 9.363,31.585C9.417,31.538 9.455,31.467 9.477,31.373L9.629,30.738H9.795L9.639,31.389C9.605,31.53 9.545,31.636 9.459,31.706C9.372,31.776 9.259,31.811 9.119,31.811C8.979,31.811 8.882,31.776 8.83,31.706C8.777,31.636 8.768,31.53 8.802,31.389L8.958,30.738Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M9.773,31.783L10.033,30.697L10.528,31.336C10.541,31.354 10.554,31.373 10.568,31.393C10.581,31.414 10.594,31.437 10.608,31.463L10.782,30.738H10.935L10.675,31.824L10.17,31.174C10.156,31.156 10.144,31.138 10.132,31.118C10.12,31.098 10.109,31.078 10.099,31.057L9.925,31.783H9.773Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M10.921,31.783L11.172,30.738H11.337L11.087,31.783H10.921Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M11.325,31.783L11.576,30.738H12.144L12.11,30.882H11.707L11.644,31.143H12.047L12.012,31.292H11.608L11.491,31.783H11.325Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M12.078,31.783L12.328,30.738H12.494L12.243,31.783H12.078Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M12.481,31.783L12.731,30.738H13.3L13.266,30.882H12.863L12.8,31.144H13.203L13.167,31.294H12.764L12.683,31.631H13.086L13.05,31.783H12.481Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M13.443,31.63H13.582C13.658,31.63 13.717,31.624 13.758,31.614C13.799,31.604 13.836,31.586 13.871,31.561C13.917,31.528 13.956,31.486 13.988,31.435C14.019,31.385 14.042,31.327 14.058,31.26C14.074,31.193 14.079,31.135 14.071,31.085C14.064,31.035 14.045,30.993 14.015,30.959C13.992,30.934 13.962,30.917 13.924,30.906C13.887,30.896 13.825,30.89 13.74,30.89H13.68H13.62L13.443,31.63ZM13.24,31.783L13.491,30.738H13.714C13.859,30.738 13.96,30.746 14.016,30.761C14.071,30.776 14.117,30.801 14.153,30.836C14.201,30.882 14.231,30.941 14.245,31.014C14.257,31.086 14.253,31.169 14.231,31.261C14.208,31.354 14.174,31.436 14.126,31.508C14.078,31.58 14.02,31.639 13.95,31.685C13.896,31.721 13.84,31.746 13.779,31.761C13.719,31.776 13.628,31.783 13.508,31.783H13.464H13.24Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M15.038,31.175H15.081C15.173,31.175 15.237,31.165 15.272,31.144C15.308,31.124 15.332,31.088 15.344,31.036C15.357,30.98 15.351,30.941 15.323,30.918C15.296,30.895 15.238,30.884 15.151,30.884H15.108L15.038,31.175ZM14.995,31.314L14.882,31.783H14.727L14.977,30.738H15.228C15.302,30.738 15.356,30.743 15.389,30.751C15.422,30.759 15.449,30.773 15.471,30.792C15.497,30.816 15.514,30.849 15.523,30.89C15.531,30.931 15.529,30.976 15.517,31.026C15.505,31.075 15.485,31.121 15.457,31.163C15.429,31.205 15.396,31.238 15.358,31.261C15.328,31.281 15.294,31.294 15.257,31.302C15.22,31.31 15.164,31.314 15.09,31.314H15.057H14.995Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M15.72,31.373H16.004L15.956,31.134C15.954,31.119 15.952,31.102 15.95,31.082C15.948,31.062 15.947,31.04 15.946,31.016C15.935,31.039 15.924,31.06 15.913,31.08C15.902,31.1 15.892,31.118 15.881,31.134L15.72,31.373ZM16.08,31.783L16.028,31.514H15.624L15.442,31.783H15.268L16.021,30.697L16.254,31.783H16.08Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M16.493,31.783L16.607,31.305L16.4,30.738H16.574L16.703,31.093C16.706,31.102 16.709,31.114 16.713,31.129C16.718,31.143 16.722,31.159 16.725,31.177C16.736,31.16 16.746,31.144 16.757,31.129C16.768,31.115 16.779,31.101 16.789,31.089L17.093,30.738H17.258L16.772,31.305L16.657,31.783H16.493Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M18.074,31.267C18.074,31.259 18.076,31.237 18.081,31.2C18.084,31.17 18.087,31.144 18.089,31.124C18.079,31.148 18.068,31.172 18.054,31.196C18.041,31.219 18.025,31.244 18.008,31.268L17.608,31.825L17.477,31.257C17.472,31.234 17.468,31.211 17.465,31.189C17.462,31.167 17.46,31.146 17.459,31.124C17.453,31.146 17.446,31.169 17.437,31.193C17.428,31.217 17.418,31.242 17.406,31.268L17.173,31.783H17.021L17.522,30.694L17.665,31.353C17.667,31.364 17.67,31.381 17.674,31.406C17.678,31.43 17.682,31.46 17.687,31.495C17.704,31.465 17.728,31.427 17.76,31.381C17.769,31.369 17.775,31.359 17.779,31.353L18.231,30.694L18.217,31.783H18.063L18.074,31.267Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M18.348,31.783L18.599,30.738H19.167L19.133,30.882H18.73L18.667,31.144H19.07L19.034,31.294H18.631L18.55,31.631H18.954L18.917,31.783H18.348Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M19.108,31.783L19.368,30.697L19.863,31.336C19.876,31.354 19.889,31.373 19.903,31.393C19.916,31.414 19.929,31.437 19.943,31.463L20.117,30.738H20.27L20.01,31.824L19.505,31.174C19.491,31.156 19.479,31.138 19.467,31.118C19.455,31.098 19.444,31.078 19.434,31.057L19.26,31.783H19.108Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M20.799,30.882L20.584,31.783H20.418L20.634,30.882H20.363L20.397,30.738H21.103L21.069,30.882H20.799Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M20.97,31.574L21.118,31.511C21.119,31.558 21.133,31.594 21.161,31.618C21.188,31.642 21.228,31.655 21.28,31.655C21.33,31.655 21.372,31.641 21.408,31.613C21.444,31.585 21.467,31.547 21.478,31.5C21.493,31.438 21.456,31.384 21.369,31.336C21.356,31.329 21.347,31.323 21.34,31.32C21.242,31.264 21.179,31.213 21.152,31.168C21.126,31.122 21.12,31.067 21.136,31.001C21.156,30.916 21.201,30.847 21.27,30.794C21.339,30.741 21.42,30.715 21.511,30.715C21.586,30.715 21.646,30.73 21.689,30.759C21.733,30.789 21.757,30.832 21.764,30.888L21.618,30.956C21.605,30.923 21.588,30.899 21.568,30.884C21.547,30.869 21.521,30.861 21.489,30.861C21.445,30.861 21.406,30.873 21.375,30.897C21.343,30.921 21.322,30.952 21.312,30.993C21.297,31.055 21.341,31.114 21.443,31.168C21.451,31.172 21.457,31.176 21.461,31.178C21.551,31.226 21.609,31.272 21.635,31.317C21.662,31.363 21.667,31.42 21.651,31.488C21.627,31.587 21.578,31.665 21.503,31.724C21.429,31.782 21.339,31.811 21.236,31.811C21.149,31.811 21.083,31.791 21.037,31.75C20.992,31.709 20.969,31.65 20.97,31.574Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M22.194,31.783L22.445,30.738H22.61L22.36,31.783H22.194Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M22.6,31.783L22.86,30.697L23.355,31.336C23.368,31.354 23.382,31.373 23.395,31.393C23.408,31.414 23.421,31.437 23.435,31.463L23.609,30.738H23.762L23.502,31.824L22.997,31.174C22.983,31.156 22.971,31.138 22.959,31.118C22.947,31.098 22.936,31.078 22.927,31.057L22.753,31.783H22.6Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M24.29,30.882L24.074,31.783H23.909L24.124,30.882H23.854L23.888,30.738H24.594L24.56,30.882H24.29Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M24.47,31.783L24.72,30.738H25.289L25.254,30.882H24.851L24.788,31.144H25.192L25.156,31.294H24.753L24.672,31.631H25.075L25.039,31.783H24.47Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M25.538,31.184H25.568C25.656,31.184 25.717,31.173 25.751,31.152C25.784,31.131 25.808,31.094 25.82,31.041C25.834,30.983 25.829,30.943 25.803,30.919C25.778,30.896 25.724,30.884 25.64,30.884H25.61L25.538,31.184ZM25.496,31.316L25.384,31.783H25.229L25.479,30.738H25.711C25.778,30.738 25.83,30.743 25.865,30.752C25.9,30.761 25.929,30.776 25.95,30.797C25.976,30.822 25.992,30.855 26,30.895C26.007,30.935 26.005,30.978 25.994,31.026C25.974,31.11 25.938,31.175 25.888,31.223C25.837,31.27 25.772,31.298 25.692,31.308L25.93,31.783H25.742L25.515,31.316H25.496Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M26.029,31.783L26.279,30.738H26.848L26.813,30.882H26.41L26.348,31.143H26.751L26.715,31.292H26.312L26.194,31.783H26.029Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M27.038,31.373H27.323L27.275,31.134C27.273,31.119 27.271,31.102 27.269,31.082C27.267,31.062 27.266,31.04 27.265,31.016C27.254,31.039 27.243,31.06 27.232,31.08C27.221,31.1 27.211,31.118 27.2,31.134L27.038,31.373ZM27.398,31.783L27.347,31.514H26.943L26.76,31.783H26.586L27.34,30.697L27.573,31.783H27.398Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M28.653,30.993C28.616,30.952 28.574,30.921 28.527,30.9C28.479,30.88 28.427,30.87 28.369,30.87C28.258,30.87 28.158,30.906 28.071,30.98C27.983,31.053 27.926,31.148 27.898,31.264C27.871,31.377 27.883,31.47 27.933,31.543C27.983,31.617 28.061,31.653 28.164,31.653C28.224,31.653 28.285,31.642 28.344,31.621C28.404,31.599 28.464,31.566 28.525,31.521L28.479,31.713C28.427,31.746 28.372,31.771 28.316,31.787C28.26,31.803 28.201,31.811 28.139,31.811C28.062,31.811 27.993,31.798 27.933,31.772C27.873,31.746 27.824,31.707 27.786,31.656C27.748,31.606 27.724,31.547 27.714,31.479C27.703,31.412 27.707,31.34 27.726,31.263C27.744,31.186 27.774,31.114 27.817,31.047C27.86,30.98 27.913,30.921 27.976,30.87C28.039,30.818 28.106,30.779 28.178,30.753C28.25,30.727 28.324,30.713 28.4,30.713C28.46,30.713 28.514,30.722 28.565,30.74C28.615,30.758 28.661,30.785 28.703,30.821L28.653,30.993Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M28.669,31.783L28.919,30.738H29.488L29.453,30.882H29.05L28.987,31.144H29.39L29.355,31.294H28.951L28.871,31.631H29.274L29.237,31.783H28.669Z"
|
||||
android:fillColor="#434244"/>
|
||||
<path
|
||||
android:pathData="M25.645,29.828H24.505L26.09,24.112H27.229L25.645,29.828Z"
|
||||
android:fillColor="#66686C"/>
|
||||
<path
|
||||
android:pathData="M25.053,24.292C24.974,24.184 24.853,24.129 24.687,24.129H18.423L18.113,25.248H19.253V25.248H23.811L23.48,26.444H18.921L18.921,26.442H17.782L16.836,29.852H17.976L18.611,27.563H23.735C23.895,27.563 24.046,27.508 24.188,27.399C24.329,27.29 24.422,27.156 24.467,26.995L25.101,24.705C25.147,24.539 25.132,24.401 25.053,24.292Z"
|
||||
android:fillColor="#66686C"/>
|
||||
<path
|
||||
android:pathData="M16.174,29.471C16.111,29.697 15.905,29.854 15.67,29.854H9.792C9.632,29.854 9.513,29.799 9.435,29.69C9.357,29.581 9.34,29.446 9.385,29.285L10.819,24.128H11.959L10.678,28.734H15.239L16.52,24.128H17.66L16.174,29.471Z"
|
||||
android:fillColor="#66686C"/>
|
||||
<path
|
||||
android:pathData="M29.198,24.122L30.64,26.987L27.608,29.852L29.198,24.122Z"
|
||||
android:fillColor="#27803B"/>
|
||||
<path
|
||||
android:pathData="M28.187,24.122L29.628,26.987L26.595,29.852L28.187,24.122Z"
|
||||
android:fillColor="#E9661C"/>
|
||||
</group>
|
||||
</group>
|
||||
</vector>
|
||||
Reference in New Issue
Block a user