TP-72348 | Neil | Profile Screen OneProfile animation and drawer swipability changes (#11696)
This commit is contained in:
@@ -8,11 +8,8 @@
|
||||
package com.naviapp.home.compose.profile
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.animateColor
|
||||
import androidx.compose.animation.core.CubicBezierEasing
|
||||
import androidx.compose.animation.core.animateDp
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.core.updateTransition
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
@@ -23,7 +20,6 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
@@ -32,22 +28,13 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.geometry.CornerRadius
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.navi.base.utils.orTrue
|
||||
import com.navi.common.ui.compose.DrawerState
|
||||
@@ -57,19 +44,11 @@ import com.navi.uitron.utils.hexToComposeColor
|
||||
import com.navi.uitron.utils.orFalse
|
||||
import com.naviapp.forge.model.WidgetModelDefinition
|
||||
import com.naviapp.home.compose.activity.HomePageActivity
|
||||
import com.naviapp.home.compose.model.ContainerProperty
|
||||
import com.naviapp.home.compose.model.ProfileHeaderTransitionData
|
||||
import com.naviapp.home.compose.model.ProfileHeaderWidgetData
|
||||
import com.naviapp.home.ui.state.ProfileScreenState
|
||||
import com.naviapp.home.viewmodel.ProfileVM
|
||||
import com.naviapp.home.viewmodel.SharedVM
|
||||
import com.naviapp.utils.Constants.AnimationLabels.PROFILE_ANIMATION
|
||||
import com.naviapp.utils.Constants.AnimationLabels.PROFILE_BACKGROUND_COLOR_ANIMATION
|
||||
import com.naviapp.utils.Constants.AnimationLabels.PROFILE_CORNER_SHAPE_ANIMATION
|
||||
import com.naviapp.utils.Constants.AnimationLabels.PROFILE_PADDING_ANIMATION
|
||||
import com.naviapp.utils.Constants.DEFAULT_PROFILE_BACKGROUND_COLOR
|
||||
import com.naviapp.utils.Constants.PROFILE
|
||||
import com.naviapp.utils.Constants.PROFILE_DEFAULT_ANIMATION_TIME
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
@@ -129,8 +108,7 @@ fun ProfileScreen(
|
||||
ProfileScreenWidgetRenderer(
|
||||
widget = it,
|
||||
viewModel = profileVM,
|
||||
drawerState = drawerState,
|
||||
scrollState = { scrollState },
|
||||
drawerState = drawerState
|
||||
)
|
||||
}
|
||||
|
||||
@@ -142,8 +120,7 @@ fun ProfileScreen(
|
||||
ProfileScreenWidgetRenderer(
|
||||
widget = widget,
|
||||
viewModel = profileVM,
|
||||
drawerState = drawerState,
|
||||
scrollState = { scrollState },
|
||||
drawerState = drawerState
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -161,28 +138,11 @@ fun AnimatedProfileContent(
|
||||
content: WidgetModelDefinition<UiTronResponse>,
|
||||
viewModel: ProfileVM,
|
||||
drawerState: () -> DrawerState,
|
||||
scrollState: () -> ScrollState
|
||||
) {
|
||||
|
||||
val data = content.widgetData?.data?.get(PROFILE) as? ProfileHeaderWidgetData
|
||||
|
||||
val toolTipVisibility by remember {
|
||||
derivedStateOf {
|
||||
scrollState().value <=
|
||||
(data?.containerProperty?.scrollPercentage ?: 0.05f) * scrollState().maxValue
|
||||
}
|
||||
}
|
||||
|
||||
val transitionData = getTransitionState(data?.containerProperty) { toolTipVisibility }
|
||||
|
||||
Column(
|
||||
modifier =
|
||||
Modifier
|
||||
// Used drawBehind to save recomposition when
|
||||
// transitionData.animatedBackGroundColor.value changes
|
||||
.drawBehind { drawRect(color = transitionData.animatedBackGroundColor.value) }
|
||||
.statusBarsPadding()
|
||||
) {
|
||||
Column(modifier = Modifier.background(Color.White).statusBarsPadding()) {
|
||||
UiTronRenderer(data?.profileDetailsView?.data, viewModel)
|
||||
.Render(composeViews = data?.profileDetailsView?.parentComposeView.orEmpty())
|
||||
if (data?.oneProfileData?.isVisible.orFalse()) {
|
||||
@@ -208,135 +168,24 @@ fun AnimatedProfileContent(
|
||||
),
|
||||
exit = shrinkVertically(shrinkTowards = Alignment.Top, animationSpec = tween(100)),
|
||||
) {
|
||||
Column(
|
||||
modifier =
|
||||
Modifier.padding(
|
||||
horizontal = transitionData.animatedPadding.value,
|
||||
)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = toolTipVisibility,
|
||||
enter =
|
||||
expandVertically(
|
||||
expandFrom = Alignment.Top,
|
||||
animationSpec = tween(PROFILE_DEFAULT_ANIMATION_TIME)
|
||||
),
|
||||
exit =
|
||||
shrinkVertically(
|
||||
shrinkTowards = Alignment.Top,
|
||||
animationSpec = tween(PROFILE_DEFAULT_ANIMATION_TIME)
|
||||
),
|
||||
) {
|
||||
UiTronRenderer(data?.toolTipIconView?.data, viewModel)
|
||||
.Render(
|
||||
composeViews = data?.toolTipIconView?.parentComposeView.orEmpty()
|
||||
)
|
||||
}
|
||||
OneProfileItem(
|
||||
data = data,
|
||||
animatedCornerShape = transitionData.animatedCornerShape,
|
||||
viewModel = viewModel
|
||||
)
|
||||
}
|
||||
OneProfileItem(data = data, viewModel = viewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun OneProfileItem(
|
||||
data: ProfileHeaderWidgetData?,
|
||||
animatedCornerShape: State<Dp>,
|
||||
viewModel: ProfileVM
|
||||
) {
|
||||
private fun OneProfileItem(data: ProfileHeaderWidgetData?, viewModel: ProfileVM) {
|
||||
Column(
|
||||
Modifier.fillMaxWidth()
|
||||
// Used drawBehind to save recomposition when animatedCornerShape.value changes
|
||||
.drawBehind {
|
||||
|
||||
// Draw the rounded corner shape
|
||||
drawRoundRect(
|
||||
color = data?.oneProfileData?.backGroundColor?.hexToComposeColor ?: Color.White,
|
||||
cornerRadius = CornerRadius(animatedCornerShape.value.toPx())
|
||||
)
|
||||
|
||||
// Draw the border stroke
|
||||
data?.oneProfileData?.borderStrokeData?.let {
|
||||
val borderWidth = (it.width ?: 1f).dp.toPx()
|
||||
drawRoundRect(
|
||||
color = it.color?.hexToComposeColor ?: Color.Black,
|
||||
cornerRadius = CornerRadius(animatedCornerShape.value.toPx()),
|
||||
style = Stroke(borderWidth),
|
||||
// Reduced the total size to draw the border inside the view
|
||||
size =
|
||||
Size(
|
||||
height = size.height - borderWidth,
|
||||
width = size.width - borderWidth
|
||||
),
|
||||
// Offset the border to be drawn inside the view to avoid misalignment
|
||||
topLeft = Offset(borderWidth.div(2), borderWidth.div(2)),
|
||||
)
|
||||
}
|
||||
}
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
.background(data?.oneProfileData?.backGroundColor?.hexToComposeColor ?: Color.White)
|
||||
) {
|
||||
UiTronRenderer(data?.oneProfileView?.data, viewModel)
|
||||
.Render(composeViews = data?.oneProfileView?.parentComposeView.orEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getTransitionState(
|
||||
animateData: ContainerProperty?,
|
||||
toolTipVisibility: () -> Boolean
|
||||
): ProfileHeaderTransitionData {
|
||||
|
||||
val transition = updateTransition(targetState = toolTipVisibility(), label = PROFILE_ANIMATION)
|
||||
|
||||
val animatedPadding =
|
||||
transition.animateDp(
|
||||
label = PROFILE_PADDING_ANIMATION,
|
||||
transitionSpec = { tween(PROFILE_DEFAULT_ANIMATION_TIME) }
|
||||
) { state ->
|
||||
when (state) {
|
||||
true -> animateData?.horizontalPadding?.dp ?: 16.dp
|
||||
false -> 0.dp
|
||||
}
|
||||
}
|
||||
|
||||
val animatedCornerShape =
|
||||
transition.animateDp(
|
||||
label = PROFILE_CORNER_SHAPE_ANIMATION,
|
||||
transitionSpec = { tween(PROFILE_DEFAULT_ANIMATION_TIME) }
|
||||
) { state ->
|
||||
when (state) {
|
||||
true -> animateData?.cornerSize?.dp ?: 4.dp
|
||||
false -> 0.dp
|
||||
}
|
||||
}
|
||||
|
||||
val animatedBackGroundColor =
|
||||
transition.animateColor(
|
||||
label = PROFILE_BACKGROUND_COLOR_ANIMATION,
|
||||
transitionSpec = { tween(PROFILE_DEFAULT_ANIMATION_TIME) }
|
||||
) { state ->
|
||||
when (state) {
|
||||
true ->
|
||||
(animateData?.backGroundColor ?: DEFAULT_PROFILE_BACKGROUND_COLOR)
|
||||
.hexToComposeColor
|
||||
false -> Color.White
|
||||
}
|
||||
}
|
||||
|
||||
return remember(transition) {
|
||||
ProfileHeaderTransitionData(
|
||||
animatedPadding = animatedPadding,
|
||||
animatedCornerShape = animatedCornerShape,
|
||||
animatedBackGroundColor = animatedBackGroundColor
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Content(
|
||||
scrollState: () -> ScrollState,
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
package com.naviapp.home.compose.profile
|
||||
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.navi.common.ui.compose.DrawerState
|
||||
@@ -25,7 +24,6 @@ fun ProfileScreenWidgetRenderer(
|
||||
widget: WidgetModelDefinition<UiTronResponse>?,
|
||||
viewModel: ProfileVM,
|
||||
drawerState: () -> DrawerState,
|
||||
scrollState: () -> ScrollState,
|
||||
) {
|
||||
if (widget == null) return
|
||||
return when (widget.widgetType) {
|
||||
@@ -39,7 +37,7 @@ fun ProfileScreenWidgetRenderer(
|
||||
WidgetTypes.NATIVE_WIDGET.name -> {
|
||||
when (widget.widgetName) {
|
||||
HomeScreenCustomWidgetType.PROFILE_HEADER_WIDGET.name ->
|
||||
AnimatedProfileContent(widget, viewModel, drawerState, scrollState)
|
||||
AnimatedProfileContent(widget, viewModel, drawerState)
|
||||
HomeScreenCustomWidgetType.UPI_SETTINGS_WIDGET.name -> UPISettingSDK(drawerState)
|
||||
else -> Unit
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.navi.design.R as DesignR
|
||||
import com.navi.design.font.FontWeightEnum
|
||||
import com.navi.design.theme.getFontWeight
|
||||
import com.navi.design.theme.ttComposeFontFamily
|
||||
import com.navi.naviwidgets.R as NaviWidgetsR
|
||||
import com.navi.pay.utils.noRippleClickable
|
||||
import com.naviapp.R
|
||||
import com.naviapp.analytics.utils.NaviAnalytics
|
||||
@@ -95,19 +95,19 @@ fun NotificationScreenRenderer(
|
||||
@Composable
|
||||
fun NotificationScreenHeaderRenderer(activity: Activity) {
|
||||
ConstraintLayout(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
|
||||
val (closeIcon, title) = createRefs()
|
||||
val (backIcon, title) = createRefs()
|
||||
Image(
|
||||
modifier =
|
||||
Modifier.width(24.dp)
|
||||
.height(24.dp)
|
||||
.constrainAs(closeIcon) {
|
||||
.constrainAs(backIcon) {
|
||||
top.linkTo(parent.top)
|
||||
bottom.linkTo(parent.bottom)
|
||||
start.linkTo(parent.start)
|
||||
}
|
||||
.noRippleClickable { activity.onBackPressed() },
|
||||
painter = painterResource(id = DesignR.drawable.ic_close_purple),
|
||||
contentDescription = "Close Icon"
|
||||
painter = painterResource(id = NaviWidgetsR.drawable.arrow_left_purple),
|
||||
contentDescription = "Back Icon"
|
||||
)
|
||||
Text(
|
||||
modifier =
|
||||
|
||||
@@ -206,7 +206,7 @@ fun NaviModalNavigationDrawer(
|
||||
anchors = anchors,
|
||||
thresholds = { _, _ -> FractionalThreshold(0.5f) },
|
||||
orientation = Orientation.Horizontal,
|
||||
enabled = drawerState().isOpen,
|
||||
enabled = false,
|
||||
reverseDirection = isRtl,
|
||||
velocityThreshold = DrawerVelocityThreshold,
|
||||
resistance = null
|
||||
|
||||
Reference in New Issue
Block a user