When I post a series of photos to a personal blog I find myself editing HTML in Vim and switching back and forth to a browser to see if I have written comments in the right places and ordered the photos correctly. I could use a HTML editor to do this, but why not try FRP with Haskell? :) Apparently I sort of use FRP at work so trying out Reflex wasn’t too much of a leap.
Let’s start with the types. My basic blob of data is an image (a URL), a comment about the image, and
a flag to indicate if the image should appear in the final output:
The images have to be rendered in a particular order, so we’ll use a Map
where the integer keys provide the ordering and a is some type.
To toggle visibility in the final rendering, we flip imageVisible:
We can set the description for an image:
We can move the kth image up:
It’s not efficient to completely rebuild the map by converting
it to a list and back again, but this’ll do for now.
In terms of the user interface there are a few events to
user toggles visibility of the kth image;
user moves the kth image up;
user moves the kth image down; and
user changes the comment text for the kth image.
We’ll put these four events into our own type. The first three are of
type Event t Int where the Int is the key for the
image in question. The last one has type Event t (Int, T.Text)
since we need the key and the text that was entered into the textbox.
In Reflex, the event type is Event.
Next, imageW creates an unnumbered list of images, consisting of
a text field indicating if the image will be visible; a text box for writing a comment;
buttons to toggle visibility and move the image up and down; and finally the image itself.
ghci> :t switch
switch :: Reflex t => Behavior t (Event t a) -> Event t a
ghci> :t current
current :: Reflex t => Dynamic t a -> Behavior t a
ghci> :t switch . current
switch . current :: Reflex t => Dynamic t (Event t a) -> Event t a
This merge is also where we bring in the drag ‘n’ drop event via eventDrop which is how we get
a list of images into the dynamic map.
Try it out
To try it out without setting up Reflex, grab gallery_editor.zip, unzip it, and open gallery_editor/gallery.jsexe/index.html in your browser. Drag some images onto the top area of the page using your file manager. Tested on Ubuntu 16.