purview-0.1.0.0: src/PrepareTree.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DuplicateRecordFields #-}
module PrepareTree where
import Data.Aeson
import Component
import Events
{-|
This walks through the tree and collects actions that should be run
only once, and sets their run value to True. It's up to something
else to actually send the actions.
It also assigns a location to message and effect handlers.
-}
prepareTree :: Purview parentAction action m -> (Purview parentAction action m, [Event])
prepareTree = prepareTree' [] []
type Location = [Int]
prepareTree'
:: Location
-> Location
-> Purview parentAction action m
-> (Purview parentAction action m, [Event])
prepareTree' parentLocation location component = case component of
Attribute attrs cont ->
let result = prepareTree' parentLocation location cont
in (Attribute attrs (fst result), snd result)
Html kind children ->
let result = fmap (\(index, child) -> prepareTree' parentLocation (index:location) child) (zip [0..] children)
in (Html kind (fmap fst result), concatMap snd result)
EffectHandler _ploc _loc state handler cont ->
let
rest = fmap (prepareTree' location (0:location)) cont
in
( EffectHandler (Just parentLocation) (Just location) state handler (\state' -> fst (rest state'))
, snd (rest state)
)
Once effect hasRun cont ->
let send message =
Event
{ event = "once"
, message = toJSON message
, location = Just location
}
in if not hasRun then
let
rest = prepareTree' parentLocation location cont
in
(Once effect True (fst rest), [effect send] <> (snd rest))
else
let
rest = prepareTree' parentLocation location cont
in
(Once effect True (fst rest), snd rest)
Hide x ->
let (child, actions) = prepareTree' parentLocation location x
in (Hide child, actions)
Value x -> (Value x, [])
Text x -> (Text x, [])