Modeling a Screensaver with a Statechart, a real use case.

Carlos Galarza
3 min readFeb 22, 2019

--

Screensaver over the app

Last year I developed a touchable desktop application for a client (a museum) using Electron, React and a little custom CMS with NodeJS. The client requested that the app should have a Screensaver. The first requirements were:

  • The Screensaver should be opened at first.
  • When the user touches the Screensaver it should disappear.
  • Once disappeared, and if the user doesn’t interact with the app in 90 seconds, it should appear again.

Easy right? so let’s do it with a timeout 😉. First, we are gonna use 3 seconds as the inactive time instead of 90, I don’t wanna wait 90 seconds to test it out, also I’m gonna call this time SCREENSAVER_DELAY_MS.

At this time, the code doesn’t look so good but it’s not that hard to read. But, after showing how it’ll work, the client asked me to add one more requirement.

While the Screensaver is shown I want it to appear 5 minutes and disappear for 1 minute, and then appear 5 minutes and disappear 1 minute … and so on until the user interacts with the app.

The reason for this was to show to the user that the app is interactive, so let’s modify the code to meet the new requirement. I gonna call the new constants `SCREENSAVER_ACTIVE_TIME_MS` for the time the Screensaver is shown and `SCREENSAVER_INACTIVE_TIME_MS` for the time the Screensaver is hidden. In the code below I changed the original times, but it works like expected.

As you can see above, the code becomes more complex and difficult to read.

Modeling it with a statechart

I finally modeled it using a statechart and implemented it using XState. I used delayed transitions and found it so useful for this case. See how the final statechart code looks:

The statechart has two main states:

  • active: the Screensaver is shown, and switches between visible and hidden state until the user interacts with the app. When the user interacts with the app, the next state is inactive.
  • inactive: the Screensaver is hidden, and there is a timer for making it appear again.

I use a self-transition in the inactive state to reset the timer each time the user interacts with the app.

Note that the active state has two sub-states (is a compound state), visible and hidden, which are used to meet the latest client requirements.

In the example, I reduced the delays to be able to test it faster. Here the working code:

And that’s it! I achieved a simpler and cleaner code by modeling the Screensaver with a Statechart 🚀.

Unit Testing

It is so easy to test a statechart 👌, see some unit tests for the Screensaver machine in the machine.test.js file.

If you have any questions, please ask them in the comments, I would love to help!

If you are having process problems, facing hard technical decisions, or struggling with hard tech stuff, I offer tailored help for companies as a Fractional CTO or consultant. DM me on Twitter if you are interested, or follow me, I usually publish interesting tech/software/maker stuff.

This article is part of a series about statecharts:

Happy hacking! 🤖

Many thanks to Eric Rabbath and Erik Mogensen for giving me feedback on the article.

--

--

Carlos Galarza

Founder at codeportal.io. I love programming languages, machines, and tech! 👨🏽‍💻