{-# LANGUAGE FlexibleContexts #-} module Shpadoinkle.Html.Event.Throttle ( throttle , Throttle , runThrottle ) where import Control.Monad import Control.Monad.IO.Class import Data.Text import Data.Time.Clock import GHC.Conc import Shpadoinkle hiding (newTVarIO) newtype Throttle m a b = Throttle { runThrottle :: (a -> (Text, Prop m b)) -> a -> (Text, Prop m b) } throttleRaw :: MonadIO n => NominalDiffTime -> n ( (RawNode -> RawEvent -> JSM (Continuation m a)) -> RawNode -> RawEvent -> JSM (Continuation m a) ) throttleRaw duration = do lastTriggered <- liftIO $ newTVarIO Nothing return $ \handler rn re -> do t1 <- liftIO getCurrentTime continue <- liftIO . atomically $ do t0m <- readTVar lastTriggered case t0m of Nothing -> do writeTVar lastTriggered (Just t1) return True Just t0 -> do let continue = diffUTCTime t1 t0 > duration when continue $ writeTVar lastTriggered (Just t1) return continue if continue then handler rn re else return done throttle :: MonadIO n => NominalDiffTime -> n (Throttle m a b) throttle duration = do f <- throttleRaw duration return . Throttle $ \g x -> let (attr, p) = g x in (attr, cataProp textProp (listenerProp . f) flagProp p)