DEV Community

Lance Wicks
Lance Wicks

Posted on • Originally published at lancewicks.com on

Building a “1-2-4-All” Timer in Elm.

I have been wanting to learn Elm for a while and as I mentioned in an earlier post (https://lancewicks.com/2020/06/21/exploring-the-elm-programming-language/) I have managed on the third attempt to do so.

In the previous post I built a simple toy that displayed SVG. This time I decided to build something more practical; a timer app for the 1-2-4-All way of meeting facilitation (http://www.liberatingstructures.com/1-1-2-4-all/)

This app required “time”, specifically a countdown timer. So, it was a good opportunity to explore subscriptions in Elm. In this app I decided also to experiment with the Elm-UI package; which brings all your layout into Elm and prevents having to do CSS magic!

Elm-UI worked pretty well; I really like the ideas in elm-ui and not having to worry about CSS and to have a design system to hand. I won’t lie, it’s still ugly… but that is me not the language or package.

Being a more complicated application turned out to be helpful for my learning. I initially had a time subscription that was naive and just counted upwards. So then I simply hard coded the second thresholds to display the right text at the right time.

Later I re-wrote it. The nice thing about a typed language with an awesome compiler is that this was all pretty easy and safe. When I changed things the compiler would tell me when I needed to update something else.

The main logic looks like this:


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Start ->
            ( { model | status = True }, Cmd.none ) |> Update.andThen update PhaseOne

        Stop ->
            ( { model | status = False }, Cmd.none )

        Restart ->
            ( { model | status = True }, Cmd.none )

        PhaseOne ->
            ( { model | phase = "One", next = "Two", timer = 60 }, Cmd.none )

        PhaseTwo ->
            ( { model | phase = "Two", next = "Four", timer = 120 }, Cmd.none )

        PhaseFour ->
            ( { model | phase = "Four", next = "All", timer = 240 }, Cmd.none )

        PhaseAll ->
            ( { model | phase = "All", next = "All", timer = 300 }, Cmd.none )

        Tick _ ->
            if model.status then
                if model.timer > 0 then
                    ( { model | timer = model.timer - 1 }, Cmd.none )

                else
                    case model.next of
                        "Two" ->
                            ( { model | timer = 1 }, Cmd.none ) |> Update.andThen update PhaseTwo

                        "Four" ->
                            ( { model | timer = 1 }, Cmd.none ) |> Update.andThen update PhaseFour

                        "All" ->
                            ( { model | timer = 1 }, Cmd.none ) |> Update.andThen update PhaseAll

                        _ ->
                            ( model, Cmd.none )

            else
                ( { model | timer = model.timer - 0 }
                , Cmd.none
                )
Enter fullscreen mode Exit fullscreen mode

It’s I am sure, not very idiomatic; but it works and is I hope pretty understandable.

The full code is here: https://github.com/lancew/124all

You can play with it here: https://lancew.github.io/124all/

I was going to try and add a SVG clock or something like that to this app; but my interest is waning. Time to find a new puzzle to solve… I think rewriting https://www.judowrl.com in Elm. It is a small application I wrote in Javascript some time ago.

This will mean obtaining data from an API and so forth; so it will I hope round out the areas I have not looked at yet.

Stay tuned, if you follow me on Scuttlebutt I post more regular “dev diary” type posts on there (Look in my https://lancewicks.com/contact page for more on how to reach me on SSB).

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay