[Woo POS] Disable product list item animation
Closes: #WOOPRD-505
Description
This PR disables animation of product list items in POS, resulting in unexpected shadow artifact when switching between Products and Coupons tab in POS.
Steps to reproduce
- Go to POS
- Switch between Coupons and Products, back and forth
https://github.com/user-attachments/assets/83312bde-7779-460e-a40c-30e163704470
Testing information
The tests that have been performed
Verified the animation is not visible.
Images/gif
N/A
- [x] I have considered if this change warrants release notes and have added them to
RELEASE-NOTES.txtif necessary. Use the "[Internal]" label for non-user-facing changes.
Reviewer (or Author, in the case of optional code reviews):
Please make sure these conditions are met before approving the PR, or request changes if the PR needs improvement:
- [ ] The PR is small and has a clear, single focus, or a valid explanation is provided in the description. If needed, please request to split it into smaller PRs.
- [ ] Ensure Adequate Unit Test Coverage: The changes are reasonably covered by unit tests or an explanation is provided in the PR description.
- [ ] Manual Testing: The author listed all the tests they ran, including smoke tests when needed (e.g., for refactorings). The reviewer confirmed that the PR works as expected on big (tablet) and small (phone) in case of UI changes, and no regressions are added.
| 1 Message | |
|---|---|
| :book: | This PR is still a Draft: some checks will be skipped. |
Generated by :no_entry_sign: Danger
📲 You can test the changes from this Pull Request in WooCommerce-Wear Android by scanning the QR code below to install the corresponding build.
| App Name | WooCommerce-Wear Android | |
| Platform | ⌚️ Wear OS | |
| Flavor | Jalapeno | |
| Build Type | Debug | |
| Commit | 4c07907ec656f3d9401ee9ddedad57d537396356 | |
| Direct Download | woocommerce-wear-prototype-build-pr14067-4c07907.apk |
📲 You can test the changes from this Pull Request in WooCommerce Android by scanning the QR code below to install the corresponding build.
| App Name | WooCommerce Android | |
| Platform | 📱 Mobile | |
| Flavor | Jalapeno | |
| Build Type | Debug | |
| Commit | 4c07907ec656f3d9401ee9ddedad57d537396356 | |
| Direct Download | woocommerce-prototype-build-pr14067-4c07907.apk |
@samiuelson 👋
I am not completely certain that the solution is better than the bug in this case. Keep in mind that we are losing the visual indication to a user that new products have been added or that some of them have been removed.
https://github.com/user-attachments/assets/767ca6e5-6ab7-497b-b5eb-322d704305e1
Notice that the coupons are not flashing, but they have enabled animation, so I guess there is something we can do without disabling the animation
@samiuelson that's interesting. After merging from Trunk, it started to flash on the coupons too, so my guess is that the issue comes from listState we pass from outside
//cc @malinajirka
Codecov Report
All modified and coverable lines are covered by tests :white_check_mark:
Project coverage is 37.62%. Comparing base (
4d21c75) to head (4c07907).
Additional details and impacted files
@@ Coverage Diff @@
## trunk #14067 +/- ##
=========================================
Coverage 37.62% 37.62%
Complexity 8812 8812
=========================================
Files 1933 1933
Lines 108130 108130
Branches 14091 14091
=========================================
Hits 40682 40682
Misses 63762 63762
Partials 3686 3686
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
Good point, @kidinov! I didn't realize it will break other lazy list's animations. Reverted: 6667d56.
After merging from Trunk, it started to flash on the coupons too, so my guess is that the issue comes from listState we pass from outside
Yeah, indeed the issue is present because the lazylist state is created higher up in the hierarchy (which helps with remembering scroll position).
I'm out of ideas for now. Let me know if you have any clues, @malinajirka.
What we could try - not sure if it helps, is to replace crossFade with AnimatedVisibility. Something like
AnimatedScreenContent(visible = screenState == ScreenState.PRODUCTS) {
WooPosProductsScreen(
modifier = Modifier.padding(
horizontal = WooPosSpacing.Medium.value.toAdaptivePadding(),
),
listState = productsListState
)
}
AnimatedScreenContent(visible = screenState == ScreenState.PRODUCTS_SEARCH) {
WooPosItemsSearchScreen()
}
AnimatedScreenContent(visible = screenState == ScreenState.COUPONS) {
WooPosCouponsScreen(
modifier = Modifier.padding(
horizontal = WooPosSpacing.Medium.value.toAdaptivePadding()
),
listState = couponsListState,
)
}
@Composable
private fun AnimatedScreenContent(
visible: Boolean,
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
AnimatedVisibility(
visible = visible,
enter = androidx.compose.animation.fadeIn(animationSpec = tween(150, easing = LinearEasing)),
exit = androidx.compose.animation.fadeOut(animationSpec = tween(150, easing = LinearEasing)),
modifier = modifier
) {
content()
}
}
There are two CrossFade animations in our hierarchy, we'd need to do it for both. I'm not sure if it helps, but it should keep the lists in the compose tree even when they are not visible, so it could potentially help. I haven't tried it for this bug, it's just an idea.
@samiuelson 👋
My understanding of the issue comes from the fact that we store the lazy list state outside of the recomposition; therefore, it's applied after causing the list to be redrawn. So, for instance, this code fixes the flashing:
@Composable
fun WooPosItemsScreens(modifier: Modifier) {
val viewModel: WooPosItemsScreenViewModel = hiltViewModel()
val itemsViewModel: WooPosItemsViewModel = hiltViewModel()
val currentState = itemsViewModel.viewState.collectAsState()
val productListState = key("products_list_${currentState.value is WooPosItemsViewState.ProductList}") {
rememberLazyListState()
}
val couponsListState = key("coupons_list_${currentState.value is WooPosItemsViewState.CouponList}") {
rememberLazyListState()
}
WooPosItemsScreens(
modifier = modifier,
itemsScreens = viewModel.screenState,
productListState = productListState,
couponsListState = couponsListState
) {
viewModel.onUiEvent(WooPosItemsNavigator.WooPosItemsScreenNavigationEvent.NavigateBackToItemListScreen)
}
}
@Composable
fun WooPosItemsScreens(
modifier: Modifier,
itemsScreens: StateFlow<WooPosItemsScreenViewModel.ItemsScreens>,
productListState: LazyListState,
couponsListState: LazyListState,
onNavigateToItemsListScreen: () -> Unit
) {
val currentNavigationState = itemsScreens.collectAsState()
Box(modifier = modifier.fillMaxSize()) {
Crossfade(targetState = currentNavigationState.value, label = "LeftPaneScreen") { navigationState ->
when (navigationState) {
is WooPosItemsScreenViewModel.ItemsScreens.ItemListScreen -> {
WooPosItemsScreen(modifier = modifier, productListState, couponsListState)
}
is WooPosItemsScreenViewModel.ItemsScreens.VariationsScreen -> {
WooPosVariationsScreen(
modifier = modifier,
variableProductData = navigationState.product,
onBackClicked = { onNavigateToItemsListScreen() }
)
}
}
}
}
}
BUT it means that we loose scrolling position everytime the screens changed. We could go further and save scrolling position and restore manually but not sure how it will look like. It feels like it should be simplier solution here
Version 22.5 has now entered code-freeze, so the milestone of this PR has been updated to 22.6.
Version 22.6 has now entered code-freeze, so the milestone of this PR has been updated to 22.7.
Version 22.7 has now entered code-freeze, so the milestone of this PR has been updated to 22.8.
This needs to be approached different way, from scratch.