Levering binnen 5-7 werkdagen
4.6 out of 5 star rating on Trustpilot
Levering binnen 5-7 werkdagen
4.6 out of 5 star rating on Trustpilot
Fotoboeken

Stories

A line break almost made us lose our minds

1 januari 1970

Say konnichiwa to Sven Jonsson, one of Once Upon's app developers. From the fourth floor of Kichijoji in Tokyo, yes he lives and works there, he writes about our brand new layout engine. This major technological change that enables lots of fun solutions in the future. But this engine work has not only rolled like an Autostrada and he will now reveal one of the biggest obstacles during this project; a teeny tiny line break. By the way, are you a developer? If so you might solve the team's main concern halfway through the text.

Image of this blog post's author

Written by Sven Jonsson

sven.jonsson@onceupon.se

It's early 2021 and a long-spun development project is finally coming to an end. During this autumn we have been working on the biggest technical change so far, a layout engine that enables users to produce books quickly and smoothly on our servers, while at the same time, through a clever solution, we can show exactly how the book will look in our app. We define our layouts in html and then we use a library in the app that translates the html into views in React Native. Everything feels good, the implementation is simple and the app is lightning fast. We buy a cake* that we put in the fridge and our hands ache from all the smug high-fives we've done with each other (after we've used hand sanitizer, of course**).

But suddenly there's clouds on the horizon. When the test books where printed, we notice that sometimes the line breaks has differences between print and app. As you can understand this was extremely frustrating! This should have been discovered earlier, but with a little css this should be solved in no time. One of our developers takes on the role as investigator. We glance longingly at the cake and continue to make the app ready for launch.

Fotoboeken

... with a little css this should be solved in no time.

A few days later, or even just one day later, the developer comes back and tell us that he doesn't think there is a simple solution to this. He wonders if someone else wants to try instead. With big confident one by one raises their hand and with our lances held high, it is now time to fight that dragon. But nothing works. The dragon is a windmill and changing the css just takes the form of an advanced whack-a-mole.

What should we do? This is building up to become a perfect storm. Well, one possibility is to launch anyway and try to fix the error afterwards, but we realize quite quickly that we don't know if the problem can be solved at all with the current technology. We simply do not know how big the changes need to be in order for our function to work. The parallel development of new functionality in the app is on a technically, very thin ice. We move the cake from the fridge to the freezer and flag that the release will be delayed.

Fotoboeken

The developers now gather around the round table to envision possible solutions. Someone comes up with a creative idea, that we simply insert the text line by line and let the small changes that are between platforms be swallowed by wider lines. Slightly different spacing between words feels like a perfectly fine compromise. Everyone agrees that it can work but for it to work we need to know how long a row should be and this row length must be the same between all platforms. We found a library that does this for us, but have to run it through a web view because it uses an html canvas to measure the text.

If we had paused here and thought one more lap, it would probably have saved us a good month of development time. By the way, are you a developer and do you already have an idea of ​​what we should do instead? I can quickly let you know that we are always looking for new developers so please apply and help us avoid this type of mistake again***.

1

Read more: Work on site or remotely from e.g. a croft. We are looking for new colleagues!

One sprint later we have a prototype that works both on the server and in the app. We are doing tests on different phones to see if the text measurement library works on all platforms. The results are very promising. In passing, someone mentions the cake in the freezer. Another brave developer re-refrigerates it for slow thawing.

But then we start testing in more languages, and languages ​​that contain different alphabets. We find one problem; the font we use lack support on several character sets. Character sets that are used in Europe such as e.g. Greek and Cyrillic. It's something that has been hidden in the app before. Since the book was created on the user's phone, the reserve fonts available are used, but we realize that the book looks different or can look different on desktop versus mobile since mobile phones have different reserve fonts compared to our serve. This concludes in a difference in look between the app and the printed version.

The cake goes into the freezer once more

Fotoboeken

Oh no. Another thing we could have foreseen or find earlier. However, as we do not support these languages ​​in the app, it has not been fully tested.

As said, in this case we use a module that translates our layouts from html to React Native views and the only way to change fonts is to nest text fields inside each other. In the web view used for measuring text length, there are no problems. We only use fallback fonts in css. Clue number two about another simpler solution than the one we're about to get into.

The cake goes into the freezer once more and I take on the task. So how do I know which language is being used? Well, I need to read every single character that the user types in and translate it to unicode and at the same time extract the unicode characters from the fonts that we have and simply change the font depending on the character. Of course, it becomes a little more problematic because there is overlap between them. Our main font contains some Greek characters that had to be deleted from the huge spread of unicodes I extracted from the font files. Almost improbably, everything actually works, but somewhere I know I've created a monster that will strike back and bite us when we least expect it.

2

Read more: Interested in our tech stack? A small click here is all it takes!

And yes, new problems occur. When using longer text the app is super slow. We've used text fields even in the scroll and when the texts are longer it becomes completely unmanageable with nested text fields. I decide to take screenshots of the layout and use images instead of text fields. However, this is easier said than done. These images must be updated at the right time and work in books where multiple users collaborate. We test and bugfix, test and bugfix. We are already at the end of April and everyone just wants to get it done. Daily check-ins are sometimes interrupted by little cynical giggles and we've all had that thousand-mile stare you get if you've seen something beautiful break. Our solution had once been so simple.

That's when we realize something fundamental (something you may already realized?). How is it possible that we can measure the text correctly in a web view? We have thought that there is something special about the library and its canvas solution, but is that true? We test rendering text in a web view on all platforms and find that as long as it is exactly the same size in pixels, the text is rendered exactly the same. Of course, it is not possible to render several web views at the same time and it must be exactly the same size on all platforms. But if we render it out of frame, take a screenshot of the web view and hey; we have a solution where we can do without the monster above. We exhale for the first time in several weeks.

Honestly, though, I'm still a little proud of the monster I helped create. Perhaps you have at some point committed a small innocent crime that you got away with, e.g. shoplifted at a supermarket when you were younger. Then you know what I mean. There is shame but also, not infrequently, a sense of pride, perhaps that you dared. I'm just glad it never went live, but if you ask really nice I might take you to GitHub and show the sleeping monster.

The solution is out in operation. The cake is eaten. But we are not satisfied yet. The app has become slow when creating previews and some users have had problems updating and logging in. We are currently working on improving our current solution and are also exploring better ways to do it (including Skia). As I wrote before, we need more brains for our team, not only to solve problems of this kind, but also to develop new solutions. Let's figure out together exactly what that is.

Fotoboeken

* The cake is a lie

** The Covid-19 pandemic was still ravaging the world

*** Well, to be fair, there was actually functionality that we wanted that made us ignore exploring all the paths, but since we ended up having to skip that functionality, it would have been better to do it sooner rather than later.