{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecursiveDo #-}
{-# LANGUAGE TypeFamilies #-}
module Reflex.Bulmex.Input.Debounce
( InputStates(..)
, defStateAttr
, withInputDebounceEvt
, withInput
)
where
import Control.Monad.Fix
import Control.Monad.IO.Class (MonadIO)
import qualified Data.Text as Text
import Data.Time
import Reflex
import Reflex.Bulmex.Event
data InputStates
= InputStarted
| InputBuffered
| InputProcessed
| InputAborted
| InputInitial
withInputDebounceEvt
:: ( PostBuild t m
, MonadFix m
, MonadHold t m
, TriggerEvent t m
, MonadIO (Performable m)
, PerformEvent t m
)
=> NominalDiffTime
-> (result -> Bool)
-> (Dynamic t InputStates -> m (b, Event t inputEvt))
-> (b -> Event t inputEvt -> m (Event t result))
-> m (Event t result, b)
withInputDebounceEvt debtime succF stateF =
withInput (debounce debtime) succF
$ const
$ fmap (\(one', two) -> (one', two, one'))
. stateF
defStateAttr :: InputStates -> Text.Text
defStateAttr InputStarted = "is-warning"
defStateAttr InputBuffered = "is-warning"
defStateAttr InputProcessed = "is-success"
defStateAttr InputAborted = "is-danger"
defStateAttr InputInitial = ""
withInput
:: (PostBuild t m, MonadFix m, MonadHold t m)
=> (Event t inputEvt -> m (Event t inputEvt))
-> (result -> Bool)
-> ( Event t result
-> Dynamic t InputStates
-> m (actArgs, Event t inputEvt, finalRes)
)
-> (actArgs -> Event t inputEvt -> m (Event t result))
-> m (Event t result, finalRes)
withInput timeF isSuccessF createTypeEvt reqFunc = mdo
(someData, typeEvtImmediate, result) <- createTypeEvt postFinished areaState
typeEvtDeb <- timeF typeEvtImmediate
postFinished <- reqFunc someData typeEvtDeb
areaState <-
holdDyn InputInitial
$ leftmost
$ [ InputStarted <$ typeEvtImmediate
, InputBuffered <$ typeEvtDeb
, InputProcessed <$ (blockFalse $ isSuccessF <$> postFinished)
, InputAborted <$ (blockFalse $ not . isSuccessF <$> postFinished)
]
pure (postFinished, result)