Making of “Your Mercari History”

This post is for Day 22 of Mercari Advent Calendar 2023, brought to you by @manoj from the Mercari India’s LTV Cross Action Team.

Today, I would like to go into the details, especially the challenges faced during the development of “Your Mercari History”, a feature we have worked on and released to the users. As the name implies, it’s for showing the user’s journey from the launch of Mercari to now. We wanted to show the users the first items they had bought, listed and sold out on Mercari and also to give them a glimpse of how they have used Mercari in the past few years.

To give users an engaging experience, we wanted to make use of animations for displaying the content along with background music.

During the implementation of this feature, we faced challenges on all sides including backend, client, and design. I will mostly focus on the client (especially iOS) and design issues faced and how we tackled them.

Before we start, this is the end result we were able to achieve with your mercari history.

Technologies used

To give users an engaging experience, we wanted to make use of animations for displaying the content along with background music.

However, creating long animations and especially displaying them on the apps can be quite complicated. There were several constraints that guided us on the technologies that we chose.

  • The animations need to be displayed on both iOS and Android applications, and they need to behave similarly on both platforms.
  • The elements of the animation, like text, images, and graphs, need to be modifiable based on the user content.
    • For example, if we are showing an item, the image of the item and the text also need to be animated along with the other contents in the animation. Otherwise, the content might look completely separate from the animation and might also cause alignment problems depending on the device form factor.
  • The designers should be able to modify the animations easily and independently from developers to ensure parallel implementation of the feature.

Based on these points, we decided to go with the Lottie framework for our use case.

What is Lottie?

Lottie is a cross-platform library that natively renders vector-based animations exported in the Bodymovin JSON format.

The animation JSON file can be created and exported by making use of the bodymovin After Effects plugin. This allows the designers to create the animations for the apps directly on Adobe After Effects without involving engineers. And since it uses JSON format, the animation file size can be tiny compared to video files.

Other animation solutions considered include

  • creating animations natively
    • Implementing these animations natively will need a lot of work from the app developers and also will be subject to feature availability on each platform.
    • There may able be an idea translation discrepancy between what the designers want and what the devs have implemented. Also, the implementation might differ on both platforms and will require in-depth QA on the animations.
  • Rive
    • Rive is a tool that allows developers to create and ship beautiful, interactive animations to any platform.
    • But both designers and developers will need to be onboarded with the platform, whereas, for Lottie, designers can use Adobe After Effects directly to generate the animation file.

Regarding the codebase, we were using SwiftUI on iOS and Jetpack Compose on Android.

The Lottie support for SwiftUI was pretty limited. So, we created custom SwiftUI wrappers around the UIKit LottieAnimationView provided by the Lottie framework. This allowed us to customize the view, and also to use the complete feature set of UIKit’s Lottie View.

Challenges

To experiment with Lottie, we got a sample design file from the designers, exported with bodymovin, and we were all excited to start working on it, but things were not straightforward, and we faced several issues, especially since it’s our first time using Lottie with so many customizations.

1. Replacing text in the animation

Lottie framework supports replacing text present in the animation with other text. We wanted to use this feature to replace some of the text in the animation based on user data.

We tried replacing the text in the sample file provided by the designers with a different string by using the TextProvider protocol from the Lottie iOS framework and TextDelegates from the Lottie Android framework. Still, it wasn’t getting replaced at all.

We could swap the text easily with some of the free animation files available on LottieFiles, which allowed us to narrow down the issue to the animation file.

On further investigation, we found that for the dynamic text swapping to work, the text needs to be made configurable on After Effects by using expressions. We eventually solved this concern and supported swapping the texts on the client side.

2. Multiline dynamic text

Some of the texts in the animation, like user reviews and item names are pretty long and can take more lines.

We tried swapping with longer texts, but the text wasn’t wrapping to the next line and was going over the screen’s bounds.

By using escaping characters like \n and \r, the text wrapping worked as expected, but it is difficult to calculate the exact wrapping position based on the screen width, and we can’t introduce line breaks in the middle of the words. Using the CoreText framework in iOS, we can probably calculate the exact line breaks, but the code can become complicated.

We investigated the library and found code that supports displaying paragraph multiline text. On debugging with our animation file, the text config was missing a size sz parameter, which was needed to auto-support text wrapping on the client side.

On further investigation, the designers found that there are two ways of setting text in After Effects.

  1. Point-based text:
    It doesn’t have any bounds, and the text is usually one line. It does support line breaks using escaping characters, though.
  2. Paragraph text box:
    The text element needs to be created with a box, and the size of the box will be the bounds for the text. By limiting the width of the box, the text wrapping automatically works, even for dynamic text.

By making use of paragraph text, we were able to make multiline text wrapping work.

3. Swapping images

There were several images in the animation like item and user profile thumbnails, which needed to be animated along with other contents. The animation was created using sample images and we wanted to swap them with the actual data.

Lottie framework has AnimationImageProvider protocol on iOS and ImageAssetDelegate for Android to support swapping the images that were part of the animation.

By making use of these, we were able to support swapping the images easily.
We also had to support downloading the images from a URL and providing them to LottieAnimationView on iOS with the image provider. We did it by manually managing the download states of the images on the swiftUI view and then injecting the results into the LottieAnimationView using SwiftUI Bindings.

4. Skipping animation content based on user taps

The animation content is divided into multiple sections. For example, there is a section for showing the first items the user has listed, sold, and purchased, another one that shows the percentage of sales and purchases by the user, and one for showing reviews from other users on the items sold on mercari.

Once the user is done checking the contents of the current section, we want to allow them to jump directly to the next section by tapping on the right side of the screen. To go back to the previous section, they can just tap on the left side of the screen.

To support this, we used the Named Markers of the Lottie animation. A marker is a point in the animation. Each marker has a start time and duration. With the help of the Lottie client libraries, we were able to play a particular marker’s complete duration, allowing us to support the expected user interactions.

5. Showing the animation progress per marker

Since we had multiple sections in the animation, to give the users a sense of progress, we wanted to show the animation progress by using the Instagram story style progress UI.

By using marker duration and tracking the real-time animation progress, we could achieve this behavior.

6. Animating graphs based on user data

To show the percentage of sales vs. item purchases of the user, we wanted to display it as pie charts, which were also part of the animation.

Since the values of these charts are different for different users, we need to animate them according to the user data. We found that there were no direct solutions provided by the Lottie framework to update these values of the animation directly. However, the animation values could be updated by updating the JSON animation file.

Decoding the JSON and updating the values can be done, but doing this on background threads delays the animation display by several seconds due to the size of the JSON file, and doing this on the main thread will block user interactions. Also, we didn’t want to fork the Lottie repository to add this support, as maintaining it would be complicated, and we didn’t want to delay the release.

To avoid affecting user experience, we decided to display the percentage values as text.

7. Huge animation file size

After adding all the details to the animation, the final JSON file size was around ~8MB for an animation duration of 1 minute. The download size was around 2MB after using gzip content encoding on CDN.

We were planning to download the file when the user opened the screen and cache it on the device, but considering the limited bandwidth offered by Japanese mobile networks, we still felt it could be better. We could have also added the file with AppBundle, but this will increase the app size for all the users.

Thanks to help from some good folks from our architect team who had prior experience with Lottie, we found there were many effects that were taking up a lot of space on the animation objects such as the spray effect. By removing these extra effects, we were able to reduce the lottie file size to 1.2MB and the download size of ~800KB.

8. Supporting sharing the screenshots

We wanted to allow users to share the screenshots of the animation on social media to encourage more engagement among mercari users.

For taking the screenshots programmatically, we need an animation view with running animation and move to the position to capture the view. But, creating a copy of the animation view just for screenshots could result in higher memory consumption on the device and also could slow down the app.

To improve this, we took the screenshots just after the animation finished loading and stored them in the view state, which were displayed on the sharing screen at the end of the animation.

Conclusion

After tackling all these problems, we released “Your Mercari History” to the users.
Also, we received very positive reactions from users uploading the posts on X (formerly Twitter) and it was great seeing a lot of members share their history on social media.

I would like to thank all the members who were responsible for developing and releasing this feature, especially:
PM: Furufuru
EM: Prasanna
Designers: Keiko, Gu Megu
iOS: Sachin Nautiyal, Manoj, Samkit, Raj Aryan
Android: Kiran, Prajwal, Vaibhav
Backend: Anand, Sudev, Sidhanth Shubham
QA: Divya Chaudhary

Working on this feature was especially fun for engineers, designers and others involved, as solving challenges gives you enough confidence and motivation to continue improving.
Looking forward to making use of Lottie to release similar exciting features in the future. See you next time.

Tomorrow’s article will be by @mtsuka, the Director of Foundation Engineering at Mercari. Do look forward to it!

  • X
  • Facebook
  • linkedin
  • このエントリーをはてなブックマークに追加