Upgrading to Elm 0.19 in early 2019

So I finally got round to updating this Elm App (for presentations) to Elm 0.19 (along with cutting out a bunch of features so it was better example app for people wanting to make Elm presentations. The result is at: Elm Present.

I assumed it would be pretty easy. I wasn't doing anything too fancy and had a very small number of dependencies (nearly all core and with one Evan-special). It wasn't.

I started out by trying to do manually, assuming it would be pretty easy. After wasting half an hour I threw that away and started again with Elm Upgrade.

While this sorted out the elm.json file it left a lot to do. I already knew about the new String.fromFloat etc in place of toString so those were easy. (I don't buy the rationale here at all! In a front end focused ecosystem making it harder to convert to strings is ridiculous and String Interpolation an obvious missing feature)

Keyboard

This was the worst part. I just wanted to do some simple things triggered by particular keys. And basically all the stuff I was using didn't exist anymore. After much searching and reading of source code to figure out how to do stuff, I ended up using ohanhi/keyboard to replace the now removed(?) functionality from the core library.

I'm now using Keyboard.downs KeyDown in subscriptions, with the following message code:

import Keyboard exposing (RawKey)
type Msg
[...]
  | KeyDown RawKey
[...]

The handling and update code looks like (it was previously using integer keycodes):

keyDown : RawKey -> Presentation -> Presentation
keyDown key presentation =
    case Keyboard.rawValue key of
        "ArrowLeft" ->
            prev presentation

        "ArrowRight" ->
            next presentation

        "Escape" ->
            { presentation | position = At 0 }

        _ ->
            presentation

Animation

This was also super confusing as nothing worked in old app due to things being moved/renamed. This at least was better documented and the new API seems fine (albeit pointlessly different to old one).

I only want to do animations when between slides, so subscriptions code does and composes with other subscriptions. (Maybe a Maybe and filterMap would be a nicer solution here?)

animationSubs : Presentation -> List (Sub Msg)
animationSubs presentation =
    case presentation.position of
        At _ ->
            []

        _ ->
            [ Browser.Events.onAnimationFrameDelta TimeUpdate ]

This is the new animation frame delta code, it now passes a Float rather than a special kind of time (which can then be converted). The Float is in seconds. I use it to move slides around (in relatively nice interruptible way).

Miscellaneous

The top level thing has changed with many new options for SPA like things. Though I've heard there are significant bugs with some of these at moment.

I switched to Browser.document:

main : Program () Presentation Msg
main =
    Browser.document
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }

Conclusions

I think it took around 2 hours (though I was watching Netflix at the same time so maybe that is unfair). But the original app took about 5 hours to make so I'm not exactly impressed. It was very frustrating. One wonderful thing about Elm is how the compiler helps you. Well that doesn't work if a bunch of stuff has been renamed, removed, moved or massively changed. For what should have been a very simple update I spent a lot of time Googling, reading source code, trying things without any real idea if they'd work. I was holding off on upgrading until things settled down, expecting by now it would be fairly seamless and problem areas would be well documented. Neither expectation was met.

However, generally working with Elm is fantastic and I should emphasise that this update was a rare disappointment. Despite having not looked at the code for ages I was easily able to get up to speed and make changes.

See all posts