NTP-43715 | Nudge cache (#15394)
Signed-off-by: Naman Khurmi <naman.khurmi@navi.com>
This commit is contained in:
@@ -36,7 +36,7 @@ constructor(
|
||||
deletedItemsMap: Map<String, Set<String>>,
|
||||
lastClickedNudgeId: String,
|
||||
onSuccess:
|
||||
(
|
||||
suspend (
|
||||
nudgeListData: NudgeListData?,
|
||||
popupListData: PopupListData?,
|
||||
bottomSheetData: BottomSheetData?,
|
||||
@@ -62,11 +62,11 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleResponse(
|
||||
private suspend fun handleResponse(
|
||||
response: RepoResult<OverlayScreenStructure>,
|
||||
deletedItemsMap: Map<String, Set<String>>,
|
||||
onSuccess:
|
||||
(
|
||||
suspend (
|
||||
nudgeListData: NudgeListData?,
|
||||
popupListData: PopupListData?,
|
||||
bottomSheetData: BottomSheetData?,
|
||||
@@ -75,15 +75,15 @@ constructor(
|
||||
) {
|
||||
response.data?.screenOverlayData?.let { screenOverlayData ->
|
||||
val updatedNudgeList =
|
||||
screenOverlayData.nudgeListData?.nudgeList?.filterNot { nudge ->
|
||||
deletedItemsMap[NUDGE]?.contains(nudge.nudgeId) == true
|
||||
screenOverlayData.nudgeListData?.nudges?.filterNot { nudge ->
|
||||
deletedItemsMap[NUDGE]?.contains(nudge.id) == true
|
||||
}
|
||||
val updatedPopupList =
|
||||
screenOverlayData.popupListData?.popupList?.filterNot { popup ->
|
||||
deletedItemsMap[POPUP]?.contains(popup.popupId) == true
|
||||
}
|
||||
onSuccess(
|
||||
screenOverlayData.nudgeListData?.copy(nudgeList = updatedNudgeList),
|
||||
screenOverlayData.nudgeListData?.copy(nudges = updatedNudgeList),
|
||||
screenOverlayData.popupListData?.copy(popupList = updatedPopupList),
|
||||
screenOverlayData.bottomSheetData,
|
||||
screenOverlayData.staticNudgeData,
|
||||
@@ -91,7 +91,7 @@ constructor(
|
||||
collectRequestPopupExists =
|
||||
updatedPopupList?.any { it.popupType == COLLECT_REQUEST } ?: false
|
||||
analyticsEventTracker.screenOverlayApi(
|
||||
updatedNudgeList?.map { it.nudgeId + Constants.COMMA + it.nudgeStatus },
|
||||
updatedNudgeList?.map { it.id + Constants.COMMA + it.status },
|
||||
updatedPopupList?.mapNotNull { it.popupId },
|
||||
screenOverlayData.bottomSheetData?.bottomSheetId,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.naviapp.screenOverlay.nudge.domain.model.data
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
|
||||
typealias NudgeId = String
|
||||
|
||||
@Stable data class NudgeListData(@SerializedName("contentList") val nudges: List<Nudge>? = null)
|
||||
|
||||
@Stable
|
||||
data class Nudge(
|
||||
@SerializedName("nudge_id") val id: NudgeId? = null,
|
||||
@SerializedName("nudge_icon_url") val iconUrl: String? = null,
|
||||
@SerializedName("nudge_data") val data: NudgeStateData? = null,
|
||||
@SerializedName("nudge_status") val status: NudgeStatus = NudgeStatus.DEFAULT,
|
||||
@SerializedName("nudge_drag_enabled") val isDraggable: Boolean? = true,
|
||||
@SerializedName("nudge_dismissible_actions")
|
||||
val dismissibleActions: List<NudgeDismissibleAction>? = null,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class NudgeDismissibleAction(
|
||||
val text: String? = null,
|
||||
val illustration: String? = null,
|
||||
val backgroundColor: String? = null,
|
||||
val textColor: String? = null,
|
||||
val dismissAction: String? = null,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class NudgeDraggedStateData(
|
||||
val state: NudgeDraggedState,
|
||||
val type: NudgeDraggedStateUpdateType,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class NudgeStateData(
|
||||
@SerializedName("nudge_success_state") val successState: UiTronResponse? = null,
|
||||
@SerializedName("nudge_in_progress_state") val inProgressState: UiTronResponse? = null,
|
||||
@SerializedName("nudge_default_state") val defaultState: UiTronResponse? = null,
|
||||
)
|
||||
|
||||
enum class NudgeStatus {
|
||||
IN_PROGRESS,
|
||||
SUCCESS,
|
||||
DEFAULT,
|
||||
DISMISSED,
|
||||
}
|
||||
|
||||
enum class NudgeDraggedState {
|
||||
IDLE,
|
||||
DRAGGED,
|
||||
}
|
||||
|
||||
enum class NudgeDraggedStateUpdateType {
|
||||
DRAG,
|
||||
TOGGLE,
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.naviapp.screenOverlay.nudge.domain.model.data
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
|
||||
typealias NudgeId = String
|
||||
|
||||
@Stable
|
||||
data class NudgeListData(@SerializedName("contentList") val nudgeList: List<NudgeData>? = null)
|
||||
|
||||
@Stable
|
||||
data class NudgeData(
|
||||
@SerializedName("nudgeId") val nudgeId: NudgeId? = null,
|
||||
@SerializedName("nudgeIconUrl") val nudgeIconUrl: String? = null,
|
||||
@SerializedName("nudgeData") val nudgeUitronData: UiTronResponse? = null,
|
||||
@SerializedName("nudgeStatus") val nudgeStatus: NudgeStatus = NudgeStatus.DEFAULT,
|
||||
@SerializedName("nudgeDragEnabled") val isNudgeDragEnabled: Boolean? = true,
|
||||
@SerializedName("nudgeDismissibleActions")
|
||||
val dismissibleActionList: List<NudgeDismissibleActionData>? = null,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class NudgeDismissibleActionData(
|
||||
val actionText: String? = null,
|
||||
val actionIllustration: String? = null,
|
||||
val actionBackgroundColor: String? = null,
|
||||
val actionTextColor: String? = null,
|
||||
val dismissAction: String? = null,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class NudgeDraggedStateData(
|
||||
val state: NudgeDraggedState,
|
||||
val type: NudgeDraggedStateUpdateType,
|
||||
)
|
||||
|
||||
enum class NudgeStatus {
|
||||
IN_PROGRESS,
|
||||
SUCCESS,
|
||||
DEFAULT,
|
||||
DISMISSED,
|
||||
}
|
||||
|
||||
enum class NudgeDraggedState {
|
||||
IDLE,
|
||||
DRAGGED,
|
||||
}
|
||||
|
||||
enum class NudgeDraggedStateUpdateType {
|
||||
DRAG,
|
||||
TOGGLE,
|
||||
}
|
||||
@@ -9,7 +9,7 @@ package com.naviapp.screenOverlay.nudge.domain.model.event
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.navi.common.basemvi.UiEvent
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.Nudge
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDraggedStateData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeId
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.StaticNudgeData
|
||||
@@ -19,7 +19,7 @@ import com.naviapp.screenOverlay.nudge.domain.model.data.StaticNudgeUiState
|
||||
sealed interface NudgeEvent : UiEvent {
|
||||
data class ToggleDescriptiveView(val enabled: Boolean) : NudgeEvent
|
||||
|
||||
data class UpdateNudgeList(val data: List<NudgeData>?) : NudgeEvent
|
||||
data class UpdateNudgeList(val data: List<Nudge>?) : NudgeEvent
|
||||
|
||||
data class DismissNudge(val id: NudgeId) : NudgeEvent
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ package com.naviapp.screenOverlay.nudge.domain.model.state
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.navi.common.basemvi.UiState
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.Nudge
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDraggedStateData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeId
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.StaticNudgeData
|
||||
@@ -18,7 +18,7 @@ import com.naviapp.screenOverlay.nudge.domain.model.data.StaticNudgeData
|
||||
data class NudgeState(
|
||||
val isNudgeListVisible: Boolean,
|
||||
val descriptiveViewEnabled: Boolean,
|
||||
val nudgeList: List<NudgeData>?,
|
||||
val nudgeList: List<Nudge>?,
|
||||
val staticNudgeData: StaticNudgeData? = null,
|
||||
val nudgeDraggedStateMap: Map<NudgeId, NudgeDraggedStateData> = emptyMap(),
|
||||
val selectedDismissibleActionIndexMap: Map<NudgeId, Int> = emptyMap(),
|
||||
|
||||
@@ -45,8 +45,8 @@ class NudgeReducer : BaseReducer<NudgeState, NudgeEvent> {
|
||||
val nudgeDraggedStateMap = mutableMapOf<NudgeId, NudgeDraggedStateData>()
|
||||
|
||||
event.data?.forEach { nudgeData ->
|
||||
nudgeData.nudgeId?.let {
|
||||
nudgeDraggedStateMap[nudgeData.nudgeId] =
|
||||
nudgeData.id?.let {
|
||||
nudgeDraggedStateMap[nudgeData.id] =
|
||||
NudgeDraggedStateData(
|
||||
state = NudgeDraggedState.IDLE,
|
||||
type = NudgeDraggedStateUpdateType.TOGGLE,
|
||||
@@ -65,8 +65,8 @@ class NudgeReducer : BaseReducer<NudgeState, NudgeEvent> {
|
||||
previousState.copy(
|
||||
nudgeList =
|
||||
previousState.nudgeList?.map { nudge ->
|
||||
if (nudge.nudgeId == event.id) {
|
||||
nudge.copy(nudgeStatus = NudgeStatus.DISMISSED)
|
||||
if (nudge.id == event.id) {
|
||||
nudge.copy(status = NudgeStatus.DISMISSED)
|
||||
} else {
|
||||
nudge
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.Nudge
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDraggedStateData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeId
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeStatus
|
||||
@@ -28,7 +28,7 @@ import com.naviapp.screenOverlay.nudge.utils.modifier.BorderSides
|
||||
|
||||
@Composable
|
||||
fun NudgeContainerCollapsedState(
|
||||
nudgeList: List<NudgeData>?,
|
||||
nudgeList: List<Nudge>?,
|
||||
isDescriptiveViewEnabled: Boolean,
|
||||
onHeightChange: (Int) -> Unit,
|
||||
nudgeDraggedStateMap: Map<NudgeId, NudgeDraggedStateData>,
|
||||
@@ -40,32 +40,31 @@ fun NudgeContainerCollapsedState(
|
||||
val nudgeData =
|
||||
remember(nudgeList.getFirstNonDismissedNudge()) { nudgeList.getFirstNonDismissedNudge() }
|
||||
|
||||
val showBorder =
|
||||
remember(nudgeData?.nudgeStatus) { nudgeData?.nudgeStatus != NudgeStatus.SUCCESS }
|
||||
val showBorder = remember(nudgeData?.status) { nudgeData?.status != NudgeStatus.SUCCESS }
|
||||
|
||||
AnimatedContent(
|
||||
modifier = Modifier.onSizeChanged { onHeightChange(it.height) },
|
||||
targetState = nudgeData,
|
||||
contentKey = { it?.nudgeId },
|
||||
contentKey = { it?.id },
|
||||
contentAlignment = Alignment.BottomCenter,
|
||||
transitionSpec = {
|
||||
nudgeCollapsedStateTransitionSpec(
|
||||
isDescriptiveViewEnabled = isDescriptiveViewEnabled,
|
||||
filteredNudgeList = nudgeList.filterDeletedNudges(),
|
||||
initialNudgeId = this.initialState?.nudgeId.toString(),
|
||||
initialNudgeId = this.initialState?.id.toString(),
|
||||
)
|
||||
},
|
||||
) { data ->
|
||||
NudgeUI(
|
||||
modifier = Modifier,
|
||||
nudgeUitronRenderer = nudgeUitronRenderer,
|
||||
nudgeData = data,
|
||||
nudgeDraggedStateData = { nudgeDraggedStateMap[data?.nudgeId] },
|
||||
nudge = data,
|
||||
nudgeDraggedStateData = { nudgeDraggedStateMap[data?.id] },
|
||||
onNudgeEvent = onNudgeEvent,
|
||||
elevateFrontLayer = true,
|
||||
onNudgeEffect = onNudgeEffect,
|
||||
borderSides = if (showBorder) BorderSides.VERTICAL else BorderSides.NONE,
|
||||
selectedDismissibleActionIndex = selectedDismissibleActionIndexMap[data?.nudgeId],
|
||||
selectedDismissibleActionIndex = selectedDismissibleActionIndexMap[data?.id],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ import com.navi.elex.atoms.ElexAsyncImage
|
||||
import com.navi.elex.atoms.ElexText
|
||||
import com.navi.elex.font.FontWeightEnum
|
||||
import com.naviapp.R
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.Nudge
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDraggedState
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDraggedStateData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeId
|
||||
@@ -61,18 +61,18 @@ import com.naviapp.screenOverlay.utils.NudgeConstants.UNPAID
|
||||
|
||||
@Composable
|
||||
fun BoxScope.NudgeMiddlePillContainer(
|
||||
nudgeList: List<NudgeData>,
|
||||
nudgeList: List<Nudge>,
|
||||
isDescriptiveViewEnabled: Boolean,
|
||||
onClick: () -> Unit,
|
||||
nudgeDraggedStateMap: Map<NudgeId, NudgeDraggedStateData>,
|
||||
) {
|
||||
val firstNudge = nudgeList.firstOrNull()
|
||||
|
||||
var previousNudgeId by remember { mutableStateOf(firstNudge?.nudgeId) }
|
||||
var previousNudgeId by remember { mutableStateOf(firstNudge?.id) }
|
||||
|
||||
val isFirstNudgeReplaced = firstNudge?.nudgeId != previousNudgeId
|
||||
val isFirstNudgeReplaced = firstNudge?.id != previousNudgeId
|
||||
|
||||
LaunchedEffect(firstNudge?.nudgeId) { previousNudgeId = firstNudge?.nudgeId }
|
||||
LaunchedEffect(firstNudge?.id) { previousNudgeId = firstNudge?.id }
|
||||
|
||||
val visibilityBaseCondition by
|
||||
remember(nudgeList, isDescriptiveViewEnabled) {
|
||||
@@ -80,14 +80,12 @@ fun BoxScope.NudgeMiddlePillContainer(
|
||||
}
|
||||
|
||||
val visibilityConditionDueToUiState by
|
||||
remember(nudgeDraggedStateMap[firstNudge?.nudgeId]?.state) {
|
||||
derivedStateOf {
|
||||
nudgeDraggedStateMap[firstNudge?.nudgeId]?.state == NudgeDraggedState.IDLE
|
||||
}
|
||||
remember(nudgeDraggedStateMap[firstNudge?.id]?.state) {
|
||||
derivedStateOf { nudgeDraggedStateMap[firstNudge?.id]?.state == NudgeDraggedState.IDLE }
|
||||
}
|
||||
|
||||
val subsequentTopNudgeIcons =
|
||||
remember(nudgeList) { nudgeList.drop(1).take(2).mapNotNull { it.nudgeIconUrl } }
|
||||
remember(nudgeList) { nudgeList.drop(1).take(2).mapNotNull { it.iconUrl } }
|
||||
|
||||
val nudgeCount = remember(nudgeList) { (nudgeList.size - 1).coerceAtMost(9) }
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.Nudge
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDraggedStateData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeId
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeStatus
|
||||
@@ -34,7 +34,7 @@ import com.naviapp.screenOverlay.nudge.utils.modifier.BorderSides
|
||||
|
||||
@Composable
|
||||
fun NudgeContainerExpandedState(
|
||||
nudgeList: List<NudgeData>?,
|
||||
nudgeList: List<Nudge>?,
|
||||
isDescriptiveViewEnabled: Boolean,
|
||||
singleNudgeHeight: Int,
|
||||
nudgeDraggedStateMap: Map<NudgeId, NudgeDraggedStateData>,
|
||||
@@ -55,26 +55,26 @@ fun NudgeContainerExpandedState(
|
||||
) {
|
||||
Column {
|
||||
nudgeList?.forEachIndexed { index, nudgeData ->
|
||||
key(nudgeData.nudgeId) {
|
||||
key(nudgeData.id) {
|
||||
AnimatedVisibility(
|
||||
visible = nudgeData.nudgeStatus != NudgeStatus.DISMISSED,
|
||||
visible = nudgeData.status != NudgeStatus.DISMISSED,
|
||||
enter = EnterTransition.None,
|
||||
exit = nudgeExitTransitionInDescriptiveView(),
|
||||
) {
|
||||
NudgeUI(
|
||||
nudgeUitronRenderer = nudgeUitronRenderer,
|
||||
nudgeData = nudgeData,
|
||||
nudge = nudgeData,
|
||||
onNudgeEvent = onNudgeEvent,
|
||||
onNudgeEffect = onNudgeEffect,
|
||||
selectedDismissibleActionIndex =
|
||||
selectedDismissibleActionIndexMap[nudgeData.nudgeId],
|
||||
nudgeDraggedStateData = { nudgeDraggedStateMap[nudgeData.nudgeId] },
|
||||
selectedDismissibleActionIndexMap[nudgeData.id],
|
||||
nudgeDraggedStateData = { nudgeDraggedStateMap[nudgeData.id] },
|
||||
borderSides =
|
||||
BorderSides(
|
||||
top =
|
||||
index ==
|
||||
nudgeList.indexOfFirst {
|
||||
it.nudgeStatus == NudgeStatus.DEFAULT
|
||||
it.status == NudgeStatus.DEFAULT
|
||||
},
|
||||
bottom = true,
|
||||
),
|
||||
|
||||
@@ -32,14 +32,17 @@ import com.navi.naviwidgets.composewidget.reusable.whiteColor
|
||||
import com.navi.pay.utils.pxToDp
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
import com.navi.uitron.utils.hexToComposeColor
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.Nudge
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDraggedStateData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDraggedStateUpdateType
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.effect.NudgeEffect
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.event.NudgeEvent
|
||||
import com.naviapp.screenOverlay.nudge.ui.nudgeUI.components.FrontLayerContent
|
||||
import com.naviapp.screenOverlay.nudge.ui.nudgeUI.components.NudgeBackLayer
|
||||
import com.naviapp.screenOverlay.nudge.ui.nudgeUI.components.NudgeFrontLayer
|
||||
import com.naviapp.screenOverlay.nudge.utils.constants.NudgeColor.borderColor
|
||||
import com.naviapp.screenOverlay.nudge.utils.constants.NudgeConstants
|
||||
import com.naviapp.screenOverlay.nudge.utils.constants.NudgeConstants.DISMISS_ACTION_CLICKED
|
||||
import com.naviapp.screenOverlay.nudge.utils.constants.NudgeConstants.dismissibleActionHorizontalPadding
|
||||
import com.naviapp.screenOverlay.nudge.utils.measurement.getMaxWidthForDismissibleActionItem
|
||||
import com.naviapp.screenOverlay.nudge.utils.modifier.BorderSides
|
||||
@@ -50,7 +53,7 @@ import com.naviapp.screenOverlay.nudge.utils.root.HandleNudgeStatusChange
|
||||
fun NudgeUI(
|
||||
modifier: Modifier = Modifier,
|
||||
borderSides: BorderSides,
|
||||
nudgeData: NudgeData?,
|
||||
nudge: Nudge?,
|
||||
nudgeDraggedStateData: () -> NudgeDraggedStateData?,
|
||||
selectedDismissibleActionIndex: Int?,
|
||||
elevateFrontLayer: Boolean = false,
|
||||
@@ -58,25 +61,26 @@ fun NudgeUI(
|
||||
onNudgeEffect: (effect: NudgeEffect) -> Unit,
|
||||
nudgeUitronRenderer: @Composable (response: UiTronResponse?, modifier: Modifier) -> Unit,
|
||||
) {
|
||||
if (nudgeData == null) return
|
||||
if (nudge == null) return
|
||||
val density = LocalDensity.current
|
||||
|
||||
val nudgeId = remember(nudgeData.nudgeId) { nudgeData.nudgeId.orEmpty() }
|
||||
val nudgeId = remember(nudge.id) { nudge.id.orEmpty() }
|
||||
|
||||
var frontLayerVisibility by remember { mutableStateOf(true) }
|
||||
|
||||
var frontLayerHeight by remember(nudgeId) { mutableIntStateOf(0) }
|
||||
var frontLayerHeight by remember(nudgeId, nudge.data?.defaultState) { mutableIntStateOf(0) }
|
||||
|
||||
var isFrontLayerHeightMeasured by remember(nudgeId) { mutableStateOf(false) }
|
||||
var isFrontLayerHeightMeasured by
|
||||
remember(nudgeId, nudge.data?.defaultState) { mutableStateOf(false) }
|
||||
|
||||
val maxWidthForDismissibleAction =
|
||||
getMaxWidthForDismissibleActionItem(actions = nudgeData.dismissibleActionList).pxToDp() +
|
||||
getMaxWidthForDismissibleActionItem(actions = nudge.dismissibleActions).pxToDp() +
|
||||
dismissibleActionHorizontalPadding
|
||||
|
||||
val contextMenuWidth by
|
||||
remember(maxWidthForDismissibleAction) {
|
||||
derivedStateOf {
|
||||
maxWidthForDismissibleAction.times(nudgeData.dismissibleActionList?.size.orZero())
|
||||
maxWidthForDismissibleAction.times(nudge.dismissibleActions?.size.orZero())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,12 +97,10 @@ fun NudgeUI(
|
||||
Modifier.fillMaxWidth()
|
||||
.height(with(density) { frontLayerHeight.toDp() })
|
||||
.background(
|
||||
nudgeData.dismissibleActionList
|
||||
?.first()
|
||||
?.actionBackgroundColor
|
||||
?.hexToComposeColor ?: Color.White
|
||||
nudge.dismissibleActions?.first()?.backgroundColor?.hexToComposeColor
|
||||
?: Color.White
|
||||
),
|
||||
dismissibleActionList = nudgeData.dismissibleActionList,
|
||||
dismissibleActionList = nudge.dismissibleActions,
|
||||
dismissibleActionItemWidth = maxWidthForDismissibleAction,
|
||||
onActionItemClicked = { index ->
|
||||
onNudgeEvent(NudgeEvent.DismissibleActionClicked(nudgeId, index))
|
||||
@@ -108,6 +110,12 @@ fun NudgeUI(
|
||||
onDismissNudge = { action ->
|
||||
onNudgeEvent(NudgeEvent.DismissNudge(nudgeId))
|
||||
onNudgeEffect(NudgeEffect.OnNudgeDismissAction(nudgeId, action))
|
||||
onNudgeEffect(
|
||||
NudgeEffect.TriggerClickStreamEvent(
|
||||
eventName = DISMISS_ACTION_CLICKED,
|
||||
eventValue = mapOf(NudgeConstants.ACTION to action),
|
||||
)
|
||||
)
|
||||
},
|
||||
)
|
||||
NudgeFrontLayer(
|
||||
@@ -119,13 +127,17 @@ fun NudgeUI(
|
||||
}
|
||||
},
|
||||
nudgeDraggedStateData = nudgeDraggedStateData,
|
||||
isNudgeDragEnabled = nudgeData.isNudgeDragEnabled.orTrue(),
|
||||
isNudgeDragEnabled = nudge.isDraggable.orTrue(),
|
||||
frontLayerVisibility = frontLayerVisibility,
|
||||
contextMenuWidth = contextMenuWidth,
|
||||
frontLayerContent = {
|
||||
nudgeUitronRenderer(
|
||||
nudgeData.nudgeUitronData,
|
||||
Modifier.then(DirectionalBorderModifier(borderSides, 1.dp, borderColor)),
|
||||
FrontLayerContent(
|
||||
modifier =
|
||||
Modifier.then(
|
||||
DirectionalBorderModifier(borderSides, 1.dp, borderColor)
|
||||
),
|
||||
nudgeStateData = nudge.data,
|
||||
nudgeUitronRenderer = nudgeUitronRenderer,
|
||||
)
|
||||
},
|
||||
onNudgeDraggedStateChange = { state ->
|
||||
@@ -144,5 +156,5 @@ fun NudgeUI(
|
||||
}
|
||||
}
|
||||
|
||||
HandleNudgeStatusChange(nudgeData, onNudgeEvent, onNudgeEffect)
|
||||
HandleNudgeStatusChange(nudge, onNudgeEvent, onNudgeEffect)
|
||||
}
|
||||
|
||||
@@ -33,20 +33,20 @@ import com.navi.elex.atoms.ElexText
|
||||
import com.navi.elex.font.FontWeightEnum
|
||||
import com.navi.naviwidgets.R as NaviWidgetR
|
||||
import com.navi.uitron.utils.hexToComposeColor
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDismissibleActionData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDismissibleAction
|
||||
import com.naviapp.screenOverlay.nudge.utils.constants.NudgeAnimationConstants
|
||||
import com.naviapp.utils.Constants.EMPTY
|
||||
|
||||
@Composable
|
||||
fun NudgeDismissibleActionItem(
|
||||
item: NudgeDismissibleActionData,
|
||||
item: NudgeDismissibleAction,
|
||||
shouldExpand: () -> Boolean,
|
||||
actionWidth: Dp,
|
||||
itemContainerWidth: Dp,
|
||||
onClick: () -> Unit,
|
||||
dismissAction: () -> Unit,
|
||||
) {
|
||||
if (item.actionText == null) return
|
||||
if (item.text == null) return
|
||||
|
||||
val configuration = LocalConfiguration.current
|
||||
val maxScreenWidth = remember { configuration.screenWidthDp.dp }
|
||||
@@ -54,7 +54,7 @@ fun NudgeDismissibleActionItem(
|
||||
Row(
|
||||
modifier =
|
||||
Modifier.fillMaxHeight()
|
||||
.background(item.actionBackgroundColor?.hexToComposeColor ?: Color.Gray)
|
||||
.background(item.backgroundColor?.hexToComposeColor ?: Color.Gray)
|
||||
.clickable(
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
@@ -68,14 +68,14 @@ fun NudgeDismissibleActionItem(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
ElexAsyncImage(
|
||||
icon = item.actionIllustration,
|
||||
icon = item.illustration,
|
||||
modifier = Modifier.size(20.dp),
|
||||
contentDescription = EMPTY,
|
||||
placeholder = NaviWidgetR.drawable.image_placeholder_small,
|
||||
)
|
||||
ElexText(
|
||||
text = item.actionText,
|
||||
color = item.actionTextColor?.hexToComposeColor ?: Color.White,
|
||||
text = item.text,
|
||||
color = item.textColor?.hexToComposeColor ?: Color.White,
|
||||
fontSize = 12.sp,
|
||||
lineHeight = 18.sp,
|
||||
fontWeight = FontWeightEnum.NAVI_BODY_DEMI_BOLD,
|
||||
|
||||
@@ -24,7 +24,7 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.navi.uitron.utils.hexToComposeColor
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDismissibleActionData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDismissibleAction
|
||||
import com.naviapp.screenOverlay.nudge.ui.nudgeUI.action.NudgeDismissibleActionItem
|
||||
import com.naviapp.screenOverlay.nudge.utils.animation.nudgeDismissibleActionExitFadeAnimation
|
||||
|
||||
@@ -33,7 +33,7 @@ fun NudgeBackLayer(
|
||||
modifier: Modifier,
|
||||
selectedIndex: Int?,
|
||||
dismissibleActionItemWidth: Dp = 0.dp,
|
||||
dismissibleActionList: List<NudgeDismissibleActionData>?,
|
||||
dismissibleActionList: List<NudgeDismissibleAction>?,
|
||||
onActionItemClicked: (Int) -> Unit = {},
|
||||
onDismissNudge: (String) -> Unit,
|
||||
) {
|
||||
@@ -51,8 +51,7 @@ fun NudgeBackLayer(
|
||||
Row(
|
||||
modifier =
|
||||
Modifier.background(
|
||||
actionData.actionBackgroundColor?.hexToComposeColor
|
||||
?: Color.Gray
|
||||
actionData.backgroundColor?.hexToComposeColor ?: Color.Gray
|
||||
)
|
||||
.widthIn(min = dismissibleActionItemWidth.times(size - index))
|
||||
.fillMaxHeight()
|
||||
|
||||
@@ -18,19 +18,25 @@ import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.gestures.anchoredDraggable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDraggedState
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDraggedStateData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeStateData
|
||||
import com.naviapp.screenOverlay.nudge.handler.drag.DragAnchors
|
||||
import com.naviapp.screenOverlay.nudge.handler.drag.HandleAnchorDragStateChange
|
||||
import com.naviapp.screenOverlay.nudge.handler.drag.UpdateNudgeDraggedStateOnDrag
|
||||
import com.naviapp.screenOverlay.nudge.utils.animation.nudgeFrontLayerExitAnimationSpec
|
||||
import com.naviapp.screenOverlay.nudge.utils.animation.nudgeFrontLayerStateEnterAnimationSpec
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
@@ -90,3 +96,28 @@ fun NudgeFrontLayer(
|
||||
onNudgeUiStateChange = onNudgeDraggedStateChange,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun FrontLayerContent(
|
||||
modifier: Modifier,
|
||||
nudgeStateData: NudgeStateData?,
|
||||
nudgeUitronRenderer: @Composable (response: UiTronResponse?, modifier: Modifier) -> Unit,
|
||||
) {
|
||||
if (nudgeStateData == null) return
|
||||
Box(modifier.height(IntrinsicSize.Max)) {
|
||||
nudgeUitronRenderer(nudgeStateData.defaultState, Modifier.fillMaxHeight())
|
||||
AnimatedVisibility(
|
||||
visible = (nudgeStateData.inProgressState != null),
|
||||
enter = nudgeFrontLayerStateEnterAnimationSpec(),
|
||||
) {
|
||||
nudgeUitronRenderer(nudgeStateData.inProgressState, Modifier.fillMaxHeight())
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = (nudgeStateData.successState != null),
|
||||
enter = nudgeFrontLayerStateEnterAnimationSpec(),
|
||||
) {
|
||||
nudgeUitronRenderer(nudgeStateData.successState, Modifier.fillMaxHeight())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.IntSize
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.Nudge
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeId
|
||||
import com.naviapp.screenOverlay.nudge.utils.constants.NudgeAnimationConstants
|
||||
import com.naviapp.screenOverlay.nudge.utils.constants.NudgeAnimationConstants.defaultAnimationSpec
|
||||
@@ -38,13 +38,13 @@ fun nudgeEnterAnimation() = slideInVertically(defaultAnimationSpec()) { it.times
|
||||
fun nudgeExitAnimation() = ExitTransition.None
|
||||
|
||||
// --------------------- Nudge Collapsed State container transitions ---------------------
|
||||
fun AnimatedContentTransitionScope<NudgeData?>.nudgeCollapsedStateTransitionSpec(
|
||||
filteredNudgeList: List<NudgeData>?,
|
||||
fun AnimatedContentTransitionScope<Nudge?>.nudgeCollapsedStateTransitionSpec(
|
||||
filteredNudgeList: List<Nudge>?,
|
||||
initialNudgeId: NudgeId,
|
||||
isDescriptiveViewEnabled: Boolean,
|
||||
): ContentTransform {
|
||||
if (isDescriptiveViewEnabled) return EnterTransition.None togetherWith ExitTransition.None
|
||||
return if (filteredNudgeList?.any { it.nudgeId == initialNudgeId } == true) {
|
||||
return if (filteredNudgeList?.any { it.id == initialNudgeId } == true) {
|
||||
collapsedContainerRankChangeTransition()
|
||||
} else {
|
||||
collapsedContainerElementChangeTransition()
|
||||
@@ -96,6 +96,11 @@ fun nudgeFrontLayerExitAnimationSpec(): ExitTransition {
|
||||
return slideOutHorizontally(defaultAnimationSpec()) { -it }
|
||||
}
|
||||
|
||||
fun nudgeFrontLayerStateEnterAnimationSpec(): EnterTransition {
|
||||
return expandVertically(defaultAnimationSpec()) { 0 } +
|
||||
slideInVertically(defaultAnimationSpec()) { -it }
|
||||
}
|
||||
|
||||
// --------------------- Nudge header visibility transitions ---------------------
|
||||
fun nudgeHeaderEnterAnimation(): EnterTransition {
|
||||
return fadeIn(defaultAnimationSpec())
|
||||
|
||||
@@ -32,5 +32,9 @@ object NudgeColor {
|
||||
|
||||
object NudgeConstants {
|
||||
const val MIDDLE_PILL_CLICKED = "nudge_middle_pill_clicked"
|
||||
const val DISMISS_ACTION_CLICKED = "dismiss_action_clicked"
|
||||
const val ACTION = "action"
|
||||
val dismissibleActionHorizontalPadding = 26.dp
|
||||
const val PAID_NUDGE_ACTION = "PAID"
|
||||
const val DISMISS_NUDGE_ACTION = "DISMISS"
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
|
||||
package com.naviapp.screenOverlay.nudge.utils.extensions
|
||||
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.Nudge
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeStatus
|
||||
|
||||
fun List<NudgeData>?.filterDeletedNudges(): List<NudgeData> {
|
||||
return this?.filterNot { it.nudgeStatus == NudgeStatus.DISMISSED }.orEmpty()
|
||||
fun List<Nudge>?.filterDeletedNudges(): List<Nudge> {
|
||||
return this?.filterNot { it.status == NudgeStatus.DISMISSED }.orEmpty()
|
||||
}
|
||||
|
||||
fun List<NudgeData>?.getFirstNonDismissedNudge(): NudgeData? {
|
||||
return this?.firstOrNull { it.nudgeStatus != NudgeStatus.DISMISSED }
|
||||
fun List<Nudge>?.getFirstNonDismissedNudge(): Nudge? {
|
||||
return this?.firstOrNull { it.status != NudgeStatus.DISMISSED }
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ import androidx.compose.ui.unit.sp
|
||||
import com.navi.design.font.FontWeightEnum
|
||||
import com.navi.design.font.getFontWeight
|
||||
import com.navi.design.font.naviFontFamily
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDismissibleActionData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeDismissibleAction
|
||||
|
||||
@Composable
|
||||
fun getMaxWidthForDismissibleActionItem(actions: List<NudgeDismissibleActionData>?): Int {
|
||||
fun getMaxWidthForDismissibleActionItem(actions: List<NudgeDismissibleAction>?): Int {
|
||||
val density = LocalDensity.current
|
||||
val textMeasurer = rememberTextMeasurer()
|
||||
val baseWidthPx = with(density) { 56.dp.toPx().toInt() }
|
||||
@@ -31,12 +31,12 @@ fun getMaxWidthForDismissibleActionItem(actions: List<NudgeDismissibleActionData
|
||||
}
|
||||
|
||||
return remember(
|
||||
key1 = actions.map { it.actionText },
|
||||
key1 = actions.map { it.text },
|
||||
calculation = {
|
||||
val textWidths =
|
||||
actions
|
||||
.filter { it.actionText != null }
|
||||
.map { action -> measureActionWidth(textMeasurer, action.actionText!!) }
|
||||
.filter { it.text != null }
|
||||
.map { action -> measureActionWidth(textMeasurer, action.text!!) }
|
||||
val maxTextWidth = textWidths.maxOrNull() ?: 0
|
||||
maxOf(maxTextWidth, baseWidthPx)
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ package com.naviapp.screenOverlay.nudge.utils.root
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import com.naviapp.screenOverlay.model.OverlayItemTransitionState
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.Nudge
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeStatus
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.effect.NudgeEffect
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.event.NudgeEvent
|
||||
@@ -40,19 +40,19 @@ fun HandleExpandedStateByListSize(state: () -> NudgeState, onEvent: (event: Nudg
|
||||
*/
|
||||
@Composable
|
||||
fun HandleNudgeStatusChange(
|
||||
nudgeData: NudgeData,
|
||||
nudge: Nudge,
|
||||
onNudgeEvent: (nudgeEvent: NudgeEvent) -> Unit,
|
||||
onNudgeEffect: (effect: NudgeEffect) -> Unit,
|
||||
) {
|
||||
LaunchedEffect(
|
||||
key1 = nudgeData.nudgeStatus,
|
||||
key1 = nudge.status,
|
||||
block = {
|
||||
if (nudgeData.nudgeStatus == NudgeStatus.SUCCESS) {
|
||||
if (nudge.status == NudgeStatus.SUCCESS) {
|
||||
delay(SUCCESS_DELAY)
|
||||
onNudgeEvent(NudgeEvent.DismissNudge(id = nudgeData.nudgeId.orEmpty()))
|
||||
onNudgeEvent(NudgeEvent.DismissNudge(id = nudge.id.orEmpty()))
|
||||
onNudgeEffect(
|
||||
NudgeEffect.OnNudgeStateUpdate(
|
||||
id = nudgeData.nudgeId.orEmpty(),
|
||||
id = nudge.id.orEmpty(),
|
||||
transitionState = OverlayItemTransitionState.SUCCESS_ACKNOWLEDGED,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.naviapp.screenOverlay.usecase
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.navi.base.cache.model.NaviCacheEntity
|
||||
import com.navi.base.cache.repository.NaviCacheRepositoryImpl
|
||||
import com.navi.common.utils.log
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
import com.naviapp.network.di.DataDeserializers
|
||||
import com.naviapp.network.di.DataSerializers
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.Nudge
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeId
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeStatus
|
||||
import com.naviapp.utils.fromJsonSafely
|
||||
import javax.inject.Inject
|
||||
|
||||
class NudgeCacheUseCase
|
||||
@Inject
|
||||
constructor(
|
||||
private val naviCacheRepository: NaviCacheRepositoryImpl,
|
||||
@DataSerializers private val dataSerializer: Gson,
|
||||
@DataDeserializers private val dataDeserializer: Gson,
|
||||
) {
|
||||
suspend fun getUpdatedNudgeList(nudgeList: List<Nudge>?): List<Nudge> {
|
||||
if (nudgeList.isNullOrEmpty()) return emptyList()
|
||||
|
||||
val cachedNudges = getCachedNudges().toMutableMap()
|
||||
|
||||
return nudgeList
|
||||
.mapNotNull { nudge ->
|
||||
val nudgeId = nudge.id ?: return@mapNotNull null
|
||||
val nudgeConfig = nudge.data ?: return@mapNotNull null
|
||||
val cachedNudge = cachedNudges[nudgeId]
|
||||
|
||||
when (nudge.status) {
|
||||
NudgeStatus.DEFAULT ->
|
||||
nudgeConfig.defaultState?.let {
|
||||
cachedNudges[nudgeId] = NudgeCache(it)
|
||||
nudge.copy(
|
||||
data = nudgeConfig.copy(inProgressState = null, successState = null)
|
||||
)
|
||||
}
|
||||
|
||||
NudgeStatus.IN_PROGRESS ->
|
||||
cachedNudge?.defaultStateData?.let {
|
||||
cachedNudges[nudgeId] =
|
||||
cachedNudge.copy(inProgressStateData = nudgeConfig.inProgressState)
|
||||
nudge.copy(
|
||||
data = nudgeConfig.copy(defaultState = it, successState = null)
|
||||
)
|
||||
}
|
||||
|
||||
NudgeStatus.SUCCESS ->
|
||||
cachedNudge?.defaultStateData?.let {
|
||||
nudge.copy(
|
||||
data =
|
||||
nudgeConfig.copy(
|
||||
defaultState = it,
|
||||
inProgressState = cachedNudge.inProgressStateData,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
cachedNudges.remove(nudgeId)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
.also { cachedNudges.saveToCache(naviCacheRepository, dataSerializer) }
|
||||
}
|
||||
|
||||
suspend fun removeNudgeFromCache(nudgeId: NudgeId) {
|
||||
getCachedNudges().toMutableMap().apply {
|
||||
remove(nudgeId)
|
||||
saveToCache(naviCacheRepository, dataSerializer)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getCachedNudges(): Map<NudgeId, NudgeCache> =
|
||||
naviCacheRepository.get(HOME_NUDGE_KEY)?.let {
|
||||
dataDeserializer.fromJsonSafely(it.value, emptyMap())
|
||||
} ?: emptyMap()
|
||||
|
||||
data class NudgeCache(
|
||||
val defaultStateData: UiTronResponse? = null,
|
||||
val inProgressStateData: UiTronResponse? = null,
|
||||
)
|
||||
|
||||
private suspend fun Map<NudgeId, NudgeCache>.saveToCache(
|
||||
repository: NaviCacheRepositoryImpl,
|
||||
serializer: Gson,
|
||||
): Boolean {
|
||||
if (isEmpty()) return false
|
||||
return runCatching {
|
||||
repository.save(
|
||||
NaviCacheEntity(
|
||||
key = HOME_NUDGE_KEY,
|
||||
value = serializer.toJson(this),
|
||||
version = 1,
|
||||
ttl = -1L,
|
||||
clearOnLogout = true,
|
||||
)
|
||||
)
|
||||
true
|
||||
}
|
||||
.onFailure { it.log() }
|
||||
.getOrDefault(false)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val HOME_NUDGE_KEY = "HOME_NUDGE"
|
||||
}
|
||||
}
|
||||
@@ -22,18 +22,21 @@ import com.naviapp.screenOverlay.handler.ScreenOverlayHandler
|
||||
import com.naviapp.screenOverlay.handler.ScreenOverlayUitronActionHandler
|
||||
import com.naviapp.screenOverlay.model.OverlayItemActionData
|
||||
import com.naviapp.screenOverlay.model.OverlayItemStateUpdate
|
||||
import com.naviapp.screenOverlay.model.OverlayItemTransitionState
|
||||
import com.naviapp.screenOverlay.model.OverlayItemsStateUpdates
|
||||
import com.naviapp.screenOverlay.model.ScreenOverlayActionUpdateRequest
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeListData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.NudgeStatus
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.data.StaticNudgeData
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.event.NudgeEvent
|
||||
import com.naviapp.screenOverlay.nudge.domain.model.state.NudgeState
|
||||
import com.naviapp.screenOverlay.nudge.domain.reducer.NudgeReducer
|
||||
import com.naviapp.screenOverlay.nudge.utils.constants.NudgeConstants.DISMISS_NUDGE_ACTION
|
||||
import com.naviapp.screenOverlay.nudge.utils.constants.NudgeConstants.PAID_NUDGE_ACTION
|
||||
import com.naviapp.screenOverlay.popup.model.PopupEvent
|
||||
import com.naviapp.screenOverlay.popup.model.PopupListData
|
||||
import com.naviapp.screenOverlay.popup.model.PopupState
|
||||
import com.naviapp.screenOverlay.popup.reducer.PopupReducer
|
||||
import com.naviapp.screenOverlay.usecase.NudgeCacheUseCase
|
||||
import com.naviapp.utils.SelectiveRefreshHandler
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
@@ -53,6 +56,7 @@ constructor(
|
||||
private val screenOverlayHandler: ScreenOverlayHandler,
|
||||
private val screenOverlayUitronActionHandler: ScreenOverlayUitronActionHandler,
|
||||
private val selectiveRefreshHandler: SelectiveRefreshHandler,
|
||||
private val nudgeCacheUseCase: NudgeCacheUseCase,
|
||||
) :
|
||||
ScreenOverlayVMComponent(
|
||||
initialNudgeState = NudgeState.initialState,
|
||||
@@ -70,7 +74,6 @@ constructor(
|
||||
val deletedItemsMap = mutableMapOf<String, MutableSet<String>>()
|
||||
private var fetchOverlayScreenApiJob: Job? = null
|
||||
private var lastClickedNudgeId = EMPTY
|
||||
private var lastViewedNudgeIds = mutableSetOf<String>()
|
||||
|
||||
init {
|
||||
viewModelScope.launch { getActionCallback().collect { onActionTriggered(it) } }
|
||||
@@ -86,6 +89,9 @@ constructor(
|
||||
OverlayItemsStateUpdates(nudgeItems = nudgeTransitionState),
|
||||
naeScreenName = naeScreenName,
|
||||
)
|
||||
nudgeTransitionState
|
||||
.filter { it.state == OverlayItemTransitionState.SUCCESS_ACKNOWLEDGED }
|
||||
.forEach { nudgeCacheUseCase.removeNudgeFromCache(it.nudgeId) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,6 +106,9 @@ constructor(
|
||||
ScreenOverlayActionUpdateRequest(nudgeItems = nudgeActions),
|
||||
naeScreenName = naeScreenName,
|
||||
)
|
||||
nudgeActions
|
||||
.filter { it.action == PAID_NUDGE_ACTION || it.action == DISMISS_NUDGE_ACTION }
|
||||
.forEach { nudgeCacheUseCase.removeNudgeFromCache(it.nudgeId) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,7 +133,6 @@ constructor(
|
||||
popupData,
|
||||
bottomSheetData,
|
||||
staticNudgeData,
|
||||
lastViewedNudgeIds,
|
||||
)
|
||||
},
|
||||
onError = { handleScreenOverlayApiError() },
|
||||
@@ -149,22 +157,15 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleScreenOverlayApiSuccess(
|
||||
private suspend fun handleScreenOverlayApiSuccess(
|
||||
nudgeListData: NudgeListData?,
|
||||
popupListData: PopupListData?,
|
||||
bottomSheetData: BottomSheetData?,
|
||||
staticNudgeData: StaticNudgeData?,
|
||||
lastViewedNudgeIds: MutableSet<String>,
|
||||
) {
|
||||
nudgeListData?.nudgeList?.let { nudgeList ->
|
||||
val updatedNudgeList =
|
||||
nudgeList.filterNot {
|
||||
it.nudgeStatus == NudgeStatus.SUCCESS && it.nudgeId !in lastViewedNudgeIds
|
||||
}
|
||||
sendEvent(NudgeEvent.UpdateNudgeList(updatedNudgeList))
|
||||
lastViewedNudgeIds.clear()
|
||||
lastViewedNudgeIds.addAll(updatedNudgeList.mapNotNull { it.nudgeId })
|
||||
}
|
||||
sendEvent(
|
||||
NudgeEvent.UpdateNudgeList(nudgeCacheUseCase.getUpdatedNudgeList(nudgeListData?.nudges))
|
||||
)
|
||||
popupListData?.popupList?.let {
|
||||
sendEvent(PopupEvent.UpdatePopupData(it, popupListVisibilityState = it.isNotEmpty()))
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ import android.widget.Toast
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.facebook.react.bridge.ReadableMap
|
||||
import com.google.common.reflect.TypeToken
|
||||
import com.google.gson.Gson
|
||||
import com.navi.base.utils.BaseUtils
|
||||
import com.navi.common.utils.Constants
|
||||
import com.navi.common.utils.Constants.EMPTY
|
||||
@@ -286,3 +288,13 @@ fun Long.formatTimeStamp(): String {
|
||||
val formatter = SimpleDateFormat("dd MMM, h:mm a", Locale.getDefault())
|
||||
return formatter.format(date)
|
||||
}
|
||||
|
||||
inline fun <reified T> Gson.fromJsonSafely(json: String?, defaultValue: T): T {
|
||||
if (json.isNullOrEmpty()) return defaultValue
|
||||
return try {
|
||||
fromJson(json, object : TypeToken<T>() {}.type)
|
||||
} catch (e: Exception) {
|
||||
e.log()
|
||||
defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class HomeCustomActionSerializer : UiTronActionSerializer() {
|
||||
NudgeUiTronActions.DRAG_NUDGE.name ->
|
||||
context?.serialize(src as NudgeDragAction, NudgeDragAction::class.java)
|
||||
NudgeUiTronActions.NUDGE_CLICKED.name ->
|
||||
context?.serialize(src as NudgeDragAction, NudgeClickAction::class.java)
|
||||
context?.serialize(src as NudgeClickAction, NudgeClickAction::class.java)
|
||||
NudgeUiTronActions.NUDGE_CTA_ACTION.name ->
|
||||
context?.serialize(src as NudgeCtaAction, NudgeCtaAction::class.java)
|
||||
PopupUitronActions.DISMISS_POPUP.name ->
|
||||
|
||||
Reference in New Issue
Block a user