Skip to content
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

[Woo POS] [Cash & Receipts] Animations #14854

Merged
merged 18 commits into from
Jan 18, 2025
Merged

Conversation

iamgabrielma
Copy link
Contributor

@iamgabrielma iamgabrielma commented Jan 13, 2025

Partially addresses #14808
#14830 should be merged first.

Description

This PR adds transitions/animations between:

  • Transition between cash payment and order success screen
Screen.Recording.2025-01-13.at.15.26.29.mov
  • Transition between order success screen and email receipt screen
Screen.Recording.2025-01-13.at.15.21.37.mov

Testing information

  • Set .acceptCashForPointOfSale flag to true
  • Within a POS transaction, selecting to pay by cash, observe that the cash collection view appears under an animated transition
  • Upon marking the order as complete (any or no amount), this also disappears with transition
  • Tapping on "send receipt" appears/disappears with transition/animation as well.

Please note that this is an intermediate PR, so is enough to focus only in the animations for the review, other work like amount validation and UI fixes are dealt on separate PRs:

We do not have specifics from design regarding what sort of transitions should happen between views, happy to iterate further or change the transition direction as needed. For reference, here's a recording from Android: p1734619950830479?thread_ts=1734615162.822509&cid=C070SJRA8DP-slack-C070SJRA8DP


  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

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 all devices (phone/tablet) and no regressions are added.

@iamgabrielma iamgabrielma added type: task An internally driven task. feature: POS labels Jan 13, 2025
@iamgabrielma iamgabrielma added this to the 21.5 milestone Jan 13, 2025
@iamgabrielma iamgabrielma requested a review from staskus January 13, 2025 08:34
@iamgabrielma iamgabrielma marked this pull request as ready for review January 13, 2025 08:34
@@ -65,7 +65,9 @@ private extension PaymentsActionButtons {
func handleSendReceiptAction() async {
let isEligible = await checkReceiptEligibility()
if isEligible {
isShowingSendReceiptView = true
withAnimation {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got different animation behaviour using withAnimation vs .animation(value:). I'm not entirely sure why, but withAnimation seems to work better despite I like less how we have to call it. For context I've tested this with iOS 17

Copy link
Contributor

@staskus staskus Jan 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What worked differently? IMHO, setting isShowingSendReceiptView = true without withAnimation is preferred since we can say exactly which views and how should apply the animation.

I suppose it can depend on where we put .animation(value:) in a view hierarchy but I haven't developed a good intuition yet on a precise way of working.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to explain it, is the same animation but looks more clunky 😅 ,definitely tricky to choose where to put it. I've removed this explicit call here: 4a392e3

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Jan 13, 2025

WooCommerce iOS📲 You can test the changes from this Pull Request in WooCommerce iOS by scanning the QR code below to install the corresponding build.

App NameWooCommerce iOS WooCommerce iOS
Build Numberpr14854-dd24890
Version21.4
Bundle IDcom.automattic.alpha.woocommerce
Commitdd24890
App Center BuildWooCommerce - Prototype Builds #12582
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

@staskus
Copy link
Contributor

staskus commented Jan 13, 2025

Please note that this is an intermediate PR, so is enough to focus only in the animations for the review, other work like amount validation and UI fixes are dealt on separate PRs:
#14830

👍 One more UI update to do is to make sure the button doesn't get smaller when it's clicked. You can notice it shrinks in a slowed-down video.

Copy link
Contributor

@staskus staskus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work!

We do not have specifics from design regarding what sort of transitions should happen between views, happy to iterate further or change the transition direction as needed. For reference, here's a recording from Android: p1734619950830479?thread_ts=1734615162.822509&cid=C070SJRA8DP-slack-C070SJRA8DP

I think:

  • Both Email Receipt and Cash Payment animations do not need to fade in / fade out
  • It would be nice if Cash Payment would slide in while the other view moves towards the opposite edge synchronously. Similar to what is done with Cart -> Checkout transition, or developer on Android.

I also noticed Android pushes both Cash and Email receipt views, while we push Cash payment but present Emails modally. I don't remember if it's deliberate or not.


Technically, I know this animation work is complicated, and requires grasping the SwiftUI view update mechanims well. Let me know if you tried to do some of the things I wrote but It wouldn't work or created other issues. We could look for reasonable solutions.

@@ -13,6 +13,7 @@ struct PointOfSaleCardPresentPaymentSuccessMessageView: View {
var body: some View {
if isShowingSendReceiptView {
POSSendReceiptView(isShowingSendReceiptView: $isShowingSendReceiptView)
.transition(.move(edge: .bottom))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that I learned is to put both animated views within a single view hierarchy so SwiftUI would understand better how to animate transitions between them. For example, VStack.

That could potentially be tried out is putting POSSendReceiptView and the rest of the success view within a single view hierarchy, for example, VStack, or HStack. You can see in the PointOfSaleDashboardView, how having an HStack allows TotalsView to slide in together while CartView slides out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also play around with geometryGroup (and geometryGroupIfSupported extension I added).

It signals SwiftUI to treat some collection of views as one, making them animate together.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrapping them in a common stack seems to improve it a bit overall. I've also tried both geometryGroup and matchedgeometry but ends with a very odd results:

__anim.using.geometrygroup.mov
__anim.using.matchedgeometry.mov

Base automatically changed from task/14808-pos-cash-views-ui-details to trunk January 14, 2025 05:36
@iamgabrielma
Copy link
Contributor Author

Thanks for the review @staskus ! I've tried several things, I'd say is more annoying to test anything else 😂 Ultimately what seems to look the best from several tries is a simple approach of:

  • Wrap both components in a in ZStack
  • Make the receipt transition .leading
  • Make the rest transition .trailing
  • Animate with .default and using isShowingSendReceiptView as value

It still jumps a bit at the end, but on normal speed I don't think it's noticeable. Let me know what you think! Happy to look into more solutions or alternatives.

__anim.simplest.approach.mov

One more UI update to do is to make sure the button doesn't get smaller when it's clicked. You can notice it shrinks in a slowed-down video.

Good catch, took me a few times to see. Addressed here: c4682de

Let me know if you tried to do some of the things I wrote but It wouldn't work or created other issues. We could look for reasonable solutions.

Apart from the videos above using geometryGroup and matchedgeometry I've also tried others like asymmetric but most of them seem to conflict due having already matchedgeometry in the child components. Just as an example, those are not committed:

__anim.using.transition.asymetric.mov
__anim.using.trailing.+.leading.on.childs.mov

@iamgabrielma iamgabrielma requested a review from staskus January 14, 2025 11:18
@staskus
Copy link
Contributor

staskus commented Jan 14, 2025

@iamgabrielma, are we planning to align these buttons? IMHO, they should be in the same place, use the same back icon, same text font, and size.

image

@staskus
Copy link
Contributor

staskus commented Jan 14, 2025

Low-priority. One more thing to log is to update this error message:

image

"To process this payment please connect the reader or choose cash."

@staskus
Copy link
Contributor

staskus commented Jan 14, 2025

The floating button drops down after coming back from Cash view. It should just stay in a static position.

Simulator.Screen.Recording.-.iPad.Air.11-inch.M2.-.2025-01-14.at.18.12.29.mp4

@staskus
Copy link
Contributor

staskus commented Jan 14, 2025

Email Receipt animates to the wrong direction, not forward but back.

Simulator.Screen.Recording.-.iPad.Air.11-inch.M2.-.2025-01-14.at.18.28.18.mp4

Copy link
Contributor

@staskus staskus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried several things, I'd say is more annoying to test anything else

Thanks!

I myself used Injection to quickly iterate through animations. Enough to make a quick change, save, and retry opening views again. No need for a rebuild.

The result still doesn't look solid to me. I know there are deficiencies in the previous screens with animations but I think it's a good opportunity to understand why something doesn't work the way we want.

I think the current Android implementation is a solid example.

Doing a full push transition from Checkout to Cash Payment view. Views stick together, separate labels or buttons are not moving on their own, the opacity doesn't change.

Some other observations:

We render the POSFloatingControlView immediately after the payment state changes to .card, but this causes the button to jump around as the view is ongoing animations. We add a new check to render the component only when the animation has finished
Updates the transition direction so showing the receipt shows up as an unidirectional from, from success to receipt, and back if needed.
Updates the localized string ID as well so the new string does show appropiately
We align the header for the cash view as the previous header on the navigation flow (cart)
@iamgabrielma
Copy link
Contributor Author

I myself used Injection to quickly iterate through animations. Enough to make a quick change, save, and retry opening views again. No need for a rebuild.

💯

The result still doesn't look solid to me. I know there are deficiencies in the previous screens with animations but I think it's a good opportunity to understand why something doesn't work the way we want.
I think the current Android implementation is a solid example.
Doing a full push transition from Checkout to Cash Payment view. Views stick together, separate labels or buttons are not moving on their own, the opacity doesn't change.

Agree that looks cleaner that way, I'm not entirely sure how I would go about pushing the view into the stack though, as currently all views in the TotalsView are presented based on state but not "pushed" into the stack? Or I'm miss-understanding how would work, which is also possible 🤔

I find the current animations/transitions and views are getting more and more complicated and could be simplified or perhaps restructured into smaller bits, or not try to reuse some other bits, which adds complexity when trying to deal with multiple cases of how the view should be presented.

Missaligned button

Sounds good. Updated on 0e62a53

Dropping floating button

Since this was rendered exclusively based on payment state, it was loaded before the animation for the rest of views was completed, which caused this jump. Fixed here: 727f9ea

__anim.update.floating.bar.being.static.mov

Animate in the opposite direction

I believe you mean to making them like an "unidirectional" flow, right? By switching the transitions here we accomplish that: 8b79c4f

__anim.update.direction.mov

Update this error message

Done! 7beca97

Let me know if this looks better, I'll check separately how we can make this easier via "pushing a view" without affecting the subviews within.

@iamgabrielma iamgabrielma requested a review from staskus January 15, 2025 06:51
Copy link
Contributor

@staskus staskus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes. Some observations:

I find the current animations/transitions and views are getting more and more complicated and could be simplified or perhaps restructured into smaller bits, or not try to reuse some other bits, which adds complexity when trying to deal with multiple cases of how the view should be presented.

Yes, it's likely and expected that we'll need to iterate and improve our animation implementation while adding new animations.

Missaligned button
Sounds good. Updated on 0e62a53

  • It's still not aligned. I don't want pixel-perfectness to be a blocker but navigation is a critical thing and merchants will be tapping an expected part of the screen to go back. These misalignments could be of annoyance.
not aligned
  • The same goes with Email Receipts which now also look very differently from what we use in < Cart and < Cash Payment.

Email Receipt Button not aligned

  • We may also need to reconsider the titles of the back buttons. While "< Cart" signifies that we're coming back to the cart, "< Cash Payment" and "< Email Receipt" signifies our current screen. But it's outside the scope of this task for sure.

Since this was rendered exclusively based on payment state, it was loaded before the animation for the rest of views was completed, which caused this jump. Fixed here: 727f9ea

  • The issue with the floating button happens because it's tied to keyboard presentation, or likely some safe area insets. The floating button shouldn't rise at all when the keyboard rises to avoid it jumping around.
Simulator.Screen.Recording.-.iPad.Air.11-inch.M2.-.2025-01-15.at.10.53.58.mp4
image
  • Regarding animations. It would be great to avoid the sudden disappearance of a view while it's getting pushed out. We can see half of the "Payment Successful" still visible before the view appears.
Simulator.Screen.Recording.-.iPad.Air.11-inch.M2.-.2025-01-15.at.10.57.52.mp4

Let me know which things you're addressing on this task and the end result you're aiming for. I judge many of these things subjectively not based on concrete goals.

@iamgabrielma
Copy link
Contributor Author

Thanks for the review again @staskus , apologies for the back and forth 🙇

Header alignment

I believe this is fully fixed now, one of the views was missing a top padding, and the receipts view being consistent I've missed entirely, so I used the same configuration than for the other views for consistency. In the video below I just open the text editor aligned to the bottom of the text so is easier to record alignment across different screens:

Screen.Recording.2025-01-17.at.11.46.17.mov

Sudden view disappearance

Using .asymetric transitions for insert/remove seems to resolve the issue I would expect to use different values on insertion and removal. If I do so, this causes a regression on how the views appear and no longer show on an "uni-directional" manner. I'm not entirely sure why, but adding the same direction to both insertion and removal works correctly.

Screen.Recording.2025-01-17.at.11.45.47.mov

Floating button/keyboard

I haven't addressed these, I can log it separately

We may also need to reconsider the titles of the back buttons. While "< Cart" signifies that we're coming back to the cart, "< Cash Payment" and "< Email Receipt" signifies our current screen. But it's outside the scope of this task for sure.

Agree, is a bit odd. I pinged design in the testing P2 regarding this issue.

Copy link
Contributor

@staskus staskus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patience 👍

The animations look good! 🚀

Floating button issue

I left one suggestion to deal with it so it would ignore keyboard altogether and won't be going one when we're dismissing the view.

Delayed keyboard dismissal issue

I think it's related to the fact that we're using custom transitions, so the view disappears later than we want to dismiss the keyboard.

I implemented the change while testing, I will make a separate PR for this (you can check the video):

#14902

Back buttons

Thanks for fixing the alignment!

The POS back button should share a single component to match each other. We have different spacing between the arrow and the text and different sizes of the arrow.

Email Receipt padding Cash Payment padding Cart button padding

Created a task:

By ignoring the keyboard safe area we can get rid of isAnimating logic for the floating button appearance-disappearance.

Co-authored-by: Povilas Staskus <povilas.staskus@automattic.com>
@iamgabrielma
Copy link
Contributor Author

I left one suggestion to deal with it so it would ignore keyboard altogether and won't be going one when we're dismissing the view.

That's interesting, I wouldn't have thought to resolve it like that. 🤔 thanks! I confirmed and committed your suggestion

@iamgabrielma iamgabrielma merged commit 99a403f into trunk Jan 18, 2025
12 checks passed
@iamgabrielma iamgabrielma deleted the task/pos-cash-view-animations branch January 18, 2025 04:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature: POS type: task An internally driven task.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants