Skip to content

Commit

Permalink
Merge pull request #12190 from woocommerce/12027-home-screen-broken-a…
Browse files Browse the repository at this point in the history
…fter-activity-death

[Woo POS] Fix for broken Home screen state after Activity death.
  • Loading branch information
malinajirka authored Aug 12, 2024
2 parents 308eada + f8a12ef commit 8583b6d
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.woocommerce.android.ui.woopos.home
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
Expand All @@ -15,7 +14,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
Expand Down Expand Up @@ -117,24 +115,12 @@ private fun WooPosHomeScreen(
label = "totalsWidthAnimatedDp"
)

val cartOverlayIntensityAnimated by animateFloatAsState(
when (state.screenPositionState) {
is WooPosHomeState.ScreenPositionState.Cart.Visible.Empty -> .6f
WooPosHomeState.ScreenPositionState.Cart.Visible.NotEmpty,
WooPosHomeState.ScreenPositionState.Checkout.NotPaid,
WooPosHomeState.ScreenPositionState.Checkout.Paid,
WooPosHomeState.ScreenPositionState.Cart.Hidden -> 0f
},
label = "cartOverlayAnimated"
)

val scrollState = buildScrollStateForNavigationBetweenState(state.screenPositionState)
WooPosHomeScreen(
state = state,
scrollState = scrollState,
productsWidthDp = productsWidthAnimatedDp,
cartWidthDp = cartWidthDp,
cartOverlayIntensity = cartOverlayIntensityAnimated,
totalsWidthDp = totalsWidthAnimatedDp,
onHomeUIEvent,
)
Expand All @@ -146,7 +132,6 @@ private fun WooPosHomeScreen(
scrollState: ScrollState,
productsWidthDp: Dp,
cartWidthDp: Dp,
cartOverlayIntensity: Float,
totalsWidthDp: Dp,
onHomeUIEvent: (WooPosHomeUIEvent) -> Unit,
) {
Expand All @@ -172,14 +157,6 @@ private fun WooPosHomeScreen(
modifier = Modifier
.width(cartWidthDp)
)
Box(
modifier = Modifier
.width(cartWidthDp)
.fillMaxHeight()
.background(
color = MaterialTheme.colors.background.copy(alpha = cartOverlayIntensity),
)
)
}
}
Row(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
package com.woocommerce.android.ui.woopos.home

import android.os.Parcelable
import androidx.annotation.StringRes
import com.woocommerce.android.R
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize

@Parcelize
data class WooPosHomeState(
val screenPositionState: ScreenPositionState,
val productsInfoDialog: ProductsInfoDialog,
val exitConfirmationDialog: WooPosExitConfirmationDialog? = null,
) {
sealed class ScreenPositionState {
) : Parcelable {
@Parcelize
sealed class ScreenPositionState : Parcelable {
@Parcelize
sealed class Cart : ScreenPositionState() {
@Parcelize
sealed class Visible : Cart() {
@Parcelize
data object Empty : Cart()

@Parcelize
data object NotEmpty : Cart()
}

@Parcelize
data object Hidden : Cart()
}

@Parcelize
sealed class Checkout : ScreenPositionState() {
@Parcelize
data object NotPaid : Checkout()

@Parcelize
data object Paid : Checkout()
}
}

sealed class ProductsInfoDialog {
@Parcelize
sealed class ProductsInfoDialog : Parcelable {
data object Hidden : ProductsInfoDialog()

data class Visible(
Expand All @@ -33,16 +49,25 @@ data class WooPosHomeState(
@StringRes val secondaryMessage: Int,
val primaryButton: PrimaryButton,
) : ProductsInfoDialog() {
@Parcelize
data class PrimaryButton(
@StringRes val label: Int,
)
) : Parcelable
}
}
}

data object WooPosExitConfirmationDialog {
@Parcelize
data object WooPosExitConfirmationDialog : Parcelable {
@IgnoredOnParcel
val title: Int = R.string.woopos_exit_confirmation_title

@IgnoredOnParcel
val message: Int = R.string.woopos_exit_confirmation_message

@IgnoredOnParcel
val confirmButton: Int = R.string.woopos_exit_confirmation_confirm_button

@IgnoredOnParcel
val dismissButton: Int = R.string.woopos_exit_confirmation_dismiss_button
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.woocommerce.android.ui.woopos.home

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.woocommerce.android.R
import com.woocommerce.android.viewmodel.getStateFlow
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
Expand All @@ -13,9 +14,12 @@ import javax.inject.Inject
class WooPosHomeViewModel @Inject constructor(
private val childrenToParentEventReceiver: WooPosChildrenToParentEventReceiver,
private val parentToChildrenEventSender: WooPosParentToChildrenEventSender,
savedStateHandle: SavedStateHandle,
) : ViewModel() {
private val _state = MutableStateFlow(
WooPosHomeState(
private val _state = savedStateHandle.getStateFlow(
scope = viewModelScope,
key = "home_state",
initialValue = WooPosHomeState(
screenPositionState = WooPosHomeState.ScreenPositionState.Cart.Hidden,
productsInfoDialog = WooPosHomeState.ProductsInfoDialog.Hidden,
exitConfirmationDialog = null
Expand Down Expand Up @@ -129,17 +133,23 @@ class WooPosHomeViewModel @Inject constructor(
}

private fun handleProductsStatusChanged(event: ChildToParentEvent.ProductsStatusChanged) {
val screenPosition = _state.value.screenPositionState
val newScreenPositionState = when (event) {
ChildToParentEvent.ProductsStatusChanged.FullScreen -> WooPosHomeState.ScreenPositionState.Cart.Hidden
ChildToParentEvent.ProductsStatusChanged.FullScreen -> {
when (screenPosition) {
is WooPosHomeState.ScreenPositionState.Cart -> WooPosHomeState.ScreenPositionState.Cart.Hidden
is WooPosHomeState.ScreenPositionState.Checkout -> screenPosition
}
}
ChildToParentEvent.ProductsStatusChanged.WithCart -> {
when (val value = _state.value.screenPositionState) {
when (screenPosition) {
WooPosHomeState.ScreenPositionState.Cart.Hidden ->
WooPosHomeState.ScreenPositionState.Cart.Visible.Empty

WooPosHomeState.ScreenPositionState.Cart.Visible.Empty,
WooPosHomeState.ScreenPositionState.Cart.Visible.NotEmpty,
WooPosHomeState.ScreenPositionState.Checkout.NotPaid,
WooPosHomeState.ScreenPositionState.Checkout.Paid -> value
WooPosHomeState.ScreenPositionState.Checkout.Paid -> screenPosition
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package com.woocommerce.android.ui.woopos.home.cart

import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
Expand Down Expand Up @@ -116,6 +117,20 @@ private fun WooPosCartScreen(
)
}
}
val cartOverlayIntensityAnimated by animateFloatAsState(
when (state.body) {
WooPosCartState.Body.Empty -> .6f
is WooPosCartState.Body.WithItems -> 0f
},
label = "cartOverlayAnimated"
)
Box(
modifier = Modifier
.fillMaxSize()
.background(
color = MaterialTheme.colors.background.copy(alpha = cartOverlayIntensityAnimated),
)
)
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ class WooPosProductsViewModel @Inject constructor(
private val productsDataSource: WooPosProductsDataSource,
private val fromChildToParentEventSender: WooPosChildrenToParentEventSender,
private val priceFormat: WooPosFormatPrice,
private val preferencesRepository: WooPosPreferencesRepository
private val preferencesRepository: WooPosPreferencesRepository,
) : ViewModel() {
private var loadMoreProductsJob: Job? = null

private val _viewState = MutableStateFlow<WooPosProductsViewState>(WooPosProductsViewState.Loading())
private val _viewState =
MutableStateFlow<WooPosProductsViewState>(WooPosProductsViewState.Loading())
val viewState: StateFlow<WooPosProductsViewState> = _viewState
.onEach { notifyParentAboutStatusChange(it) }
.stateIn(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package com.woocommerce.android.ui.woopos.home.products

import android.os.Parcelable
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import kotlinx.parcelize.Parcelize

sealed class WooPosProductsViewState(
open val reloadingProductsWithPullToRefresh: Boolean,
Expand Down Expand Up @@ -32,10 +30,9 @@ sealed class WooPosProductsViewState(
WooPosProductsViewState(reloadingProductsWithPullToRefresh)
}

@Parcelize
data class WooPosProductsListItem(
val id: Long,
val name: String,
val price: String,
val imageUrl: String?,
) : Parcelable
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.woocommerce.android.ui.woopos.home

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.SavedStateHandle
import com.woocommerce.android.R
import com.woocommerce.android.ui.woopos.util.WooPosCoroutineTestRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
Expand All @@ -21,6 +23,10 @@ class WooPosHomeViewModelTest {
@JvmField
val coroutinesTestRule = WooPosCoroutineTestRule()

@Rule
@JvmField
val rule = InstantTaskExecutorRule()

private val childrenToParentEventReceiver: WooPosChildrenToParentEventReceiver = mock()
private val parentToChildrenEventSender: WooPosParentToChildrenEventSender = mock()

Expand Down Expand Up @@ -224,8 +230,22 @@ class WooPosHomeViewModelTest {
assertFalse((viewModel.state.value.productsInfoDialog is WooPosHomeState.ProductsInfoDialog.Visible))
}

@Test
fun `given home screen is at checkout, when products are updated, then should not modify screen position`() {
whenever(childrenToParentEventReceiver.events).thenReturn(
flowOf(
ChildToParentEvent.CheckoutClicked(listOf(1)),
ChildToParentEvent.ProductsStatusChanged.FullScreen
)
)
val viewModel = createViewModel()

assertTrue(viewModel.state.value.screenPositionState is WooPosHomeState.ScreenPositionState.Checkout)
}

private fun createViewModel() = WooPosHomeViewModel(
childrenToParentEventReceiver,
parentToChildrenEventSender
parentToChildrenEventSender,
SavedStateHandle()
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,6 @@ class WooPosProductsViewModelTest {
productsDataSource,
fromChildToParentEventSender,
priceFormat,
posPreferencesRepository
posPreferencesRepository,
)
}

0 comments on commit 8583b6d

Please sign in to comment.