-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WooPos][Non Simple Product types] Retry UI for pagination errors on variations screens #12972
base: trunk
Are you sure you want to change the base?
Conversation
…new order button will take us to items list screen instead of variations screen if the user proceeded to checkout while they were in variations screen.
Generated by 🚫 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.
|
📲 You can test the changes from this Pull Request in WooCommerce Android by scanning the QR code below to install the corresponding build.
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## issue/12846-analytics-for-variations #12972 +/- ##
==========================================================================
- Coverage 39.63% 39.63% -0.01%
+ Complexity 5973 5972 -1
==========================================================================
Files 1268 1268
Lines 73276 73285 +9
Branches 10057 10061 +4
==========================================================================
+ Hits 29041 29043 +2
- Misses 41656 41661 +5
- Partials 2579 2581 +2 ☔ View full report in Codecov by Sentry. |
Where does this design come from? IMO, it doesn't match expectations from this kind of UX in a mobile app. I believe this should have:
Something like that maybe? @malinajirka @samiuelson wdyt? |
Wagner gave the designs and we had conversation about this on Slack here IMHO, I don't see any problem with this design and I don't feel it deviates from the mobile UX especially considering that this is run only on tablet devices.
If we show the error as another card with the same height as rest of the items. I can see few confusions that could arise:
What do you think? |
…where it said we support only simple physical products.
I lean towards the approach Andrei mentioned (mostly because it's a standard behavior across apps on Android), but it's ultimately Wagner's decision, so I'd defer this to him. One thing which feels broken is the animation that happens after you tap on |
With the item being so big, I have doubts that people will even understand what's going on, as your synthetical example is not what people will have. They will have a list of 20 or more products. They will scroll down where they will see an item with a shimmer effect, which after some time is replaced by a huge thing, but that huge thing won't be visible automatically. They will see, in most cases, just empty space at the bottom People will need to figure out that they need to scroll down more to find this "retry" button, and there is no necessity at all to have that thing so huge and so not in line with the rest of the items. On top of that the animation looks really wrong when things are that huge. And again, this is completely not what people got used to see in mobile apps, so clarity is really questionable here
But this is not an error screen at all. It's a contextual error. People can easily keep using the shown products if the next page is not loaded
The button in the item can be as huge as we want/need Looking into Figma design, I feel that there is a misunderstanding on the flow. In 2 out of 3 designs, there are no products shown at all. I'll ask Wagner to reconsider |
@@ -8,4 +8,5 @@ interface ContentViewState { | |||
val items: List<WooPosItem> | |||
val loadingMore: Boolean | |||
val reloadingProductsWithPullToRefresh: Boolean | |||
val errorLoadingMoreItems: Boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The state defined like that can contain invalidate states, e.g. loadingMore = true
and errorLoadingMoreItems = true
.
We probably should do something like
val paginationIndicator: PaginationIndicator
enum PaginationIndicator {
Loading, Error, None
}
By the way, ContentViewState
does not follow the naming convention of the top-level classes. It probably should be WooPosItemsViewState.
And there are a few more, e.g., ToolbarAccessibilityLabels
, for instance. And some classes that are in the items
package now, e.g., WooPosBanner
should either contain an item in them or be placed in another package
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for raising this. I had this on my list to refactor hence I kept the PR as draft. Here's the refactored state: a45bd6c
.padding( | ||
start = 16.dp.toAdaptivePadding(), | ||
end = 16.dp.toAdaptivePadding(), | ||
top = 30.dp.toAdaptivePadding(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think 30 can not be in 4dp grid. 28 or 32 should be
https://m2.material.io/design/layout/spacing-methods.html#baseline-grid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: 71ee602
@@ -100,18 +93,15 @@ class WooPosVariationsViewModel @Inject constructor( | |||
if (!variationsDataSource.canLoadMore()) { | |||
return | |||
} | |||
_viewState.value = currentState.copy(loadingMore = true) | |||
_viewState.value = currentState.copy(loadingMore = true, errorLoadingMoreItems = false) | |||
loadMoreJob?.cancel() | |||
loadMoreJob = viewModelScope.launch { | |||
val result = variationsDataSource.loadMore(productId) | |||
if (result.isSuccess) { | |||
Result.success(Unit) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this line do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no longer relevant as result of this change: a45bd6c
@@ -100,18 +93,15 @@ class WooPosVariationsViewModel @Inject constructor( | |||
if (!variationsDataSource.canLoadMore()) { | |||
return | |||
} | |||
_viewState.value = currentState.copy(loadingMore = true) | |||
_viewState.value = currentState.copy(loadingMore = true, errorLoadingMoreItems = false) | |||
loadMoreJob?.cancel() | |||
loadMoreJob = viewModelScope.launch { | |||
val result = variationsDataSource.loadMore(productId) | |||
if (result.isSuccess) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
np:
_viewState.value = if (result.isSuccess) {
currentState.copy(loadingMore = false, errorLoadingMoreItems = false)
} else {
currentState.copy(loadingMore = false, errorLoadingMoreItems = true)
}
loadMoreJob?.cancel() | ||
loadMoreJob = viewModelScope.launch { | ||
val result = variationsDataSource.loadMore(productId) | ||
if (result.isSuccess) { | ||
Result.success(Unit) | ||
if (!variationsDataSource.canLoadMore()) { | ||
_viewState.value = currentState.copy(loadingMore = false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use currentState here? _viewState.value
can be modified by the time the request comes back but you copying based on the old state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no longer relevant as result of this change: a45bd6c
…ean value to minimise the occurence of invalid states
…retry-pagination-error
import com.woocommerce.android.ui.woopos.common.composeui.toAdaptivePadding | ||
|
||
@Composable | ||
fun WooPosPaginationErrorScreen( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
np: maybe call it somehow closer to reality? WooPosPaginationErrorIndicator
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: aa38f10
@@ -317,6 +324,17 @@ fun ProductsError(onRetryClicked: () -> Unit) { | |||
} | |||
} | |||
|
|||
@Composable | |||
fun ProductsPaginationError(onRetryClicked: () -> Unit) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if it's public then it should be called with WooPos...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And in other places the same
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: 6a3b777
@@ -353,7 +371,7 @@ fun WooPosItemsScreenPreview(modifier: Modifier = Modifier) { | |||
imageUrl = null, | |||
), | |||
), | |||
loadingMore = true, | |||
paginationState = PaginationState.Loading, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shell we also have preview for the pagination error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: 6bb0870
modifier = modifier | ||
.fillMaxWidth() | ||
.height(112.dp) | ||
.clip(RoundedCornerShape(16.dp)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the goal was to mimic the product's items, then it doesn't match. Please take a look at WooPosItemsList
and copy paste the card and row setup from there
Btw, in WooPosItemsList
there is naming without WooPos
of a public ItemList
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: 19a7ed5
verticalAlignment = Alignment.CenterVertically, | ||
horizontalArrangement = Arrangement.SpaceBetween | ||
) { | ||
Row( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need 3 rows nested here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored here: 19a7ed5
WooPosPaginationErrorScreen( | ||
message = stringResource(id = R.string.woopos_items_pagination_error), | ||
primaryButton = Button( | ||
text = stringResource(id = R.string.woopos_items_pagination_load_more_label), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it's missed but in both places it's still Failed to load more items. Please try again.
with Load more
, while in preview
WooPosTheme {
WooPosPaginationErrorScreen(
message = "Error loading products",
primaryButton = Button(
text = "Load more",
click = {}
)
)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: 623125f
@WooPosPreview | ||
fun WooPosPaginationErrorScreenPreview() { | ||
WooPosTheme { | ||
WooPosPaginationErrorScreen( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am considering whether a preview with a list or a list with outer padding would be better for development and debugging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have a preview like this in WooPosItemsScreen
. Let me know if I have misunderstood your query.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it a matter of personal preference, but switching between WooPosItemsScreen
and the code in this file while changing card settings is not the most enjoyable experience. On top of that it takes time to rerender WooPosItemsScreen
as it's huge and has multiple reviews
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: 1eb6c32
} | ||
} | ||
is WooPosVariationsViewState.Loading -> ItemsLoadingIndicator( | ||
minOf(10, variableProductData.numOfVariations) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the goal is to show the exact amount of variations as loading items, then I don't understand why we need to take min from it or 10?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The goal is not to show the exact amount of loading items as variations. The goal is to show the exact amount of loading items as variations only if the variation is <= 10.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then, I don't understand the logic behind that. I think we either want to indicate the number of items we load or don't want to do it and just show a generic loading screen similar to the products. Imo this just creates confusion for both us and the users on top of that it leaks logic to the view layer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, fixed here: 8c3af25
11-28--11-37.mp411-28--11-42.mp4some things I noticed:
|
Closes: #12967
Description
This PR adds a new UI for retrying errors during paginating variations.
Along with this, this PR also does a couple of small changes:
In totals screen after payment is success. It navigates the screen back to items list screen so that when we click on "new order" button from the payment success screen, we end up on the items list screen instead of variations screen if we had proceeded to totals screen from variations screen.
Changes the messages which previously only mentioned only simple physical products can be added in POS. After this PR, it should say simple physical and variable products can be added. Below are the places where this got changed:
Design
Implementation
Testing information
Retry pagination UI
Navigate to items list after payment success
Changes to messages
Navigate to POS mode (more menu -> POS)
Ensure you see a banner that says both simple and variable products instead of just simple products
Click on learn more in the banner
Ensure the dialog also mentions both simple and variable products
Navigate to POS mode where there are no compatible products to display (no simple and variable products)
Ensure the empty state also says that only simple and variable products are compatible.
The tests that have been performed
Tested on both light and dark modes
Images/gif
pagination_retry_ui.mp4
RELEASE-NOTES.txt
if 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: