{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RecursiveDo #-}
module Reflex.Dom.WebSocket.Query (cropQueryT, runWebSocketQuery) where
import Data.Default
import Control.Monad.Fix
import Data.Text (Text)
import Data.Aeson
import Reflex
import Reflex.Dom.WebSocket
import Foreign.JavaScript.TH
import Data.Maybe
import Language.Javascript.JSaddle.Types (MonadJSM)
runWebSocketQuery :: (MonadJSM m, MonadJSM (Performable m), HasJSContext m, PostBuild t m, TriggerEvent t m, PerformEvent t m, MonadHold t m, Reflex t, ToJSON q, MonadFix m, Query q, FromJSON (QueryResult q), Additive q, Group q, Eq q)
=> QueryT t q m a
-> Text
-> m a
runWebSocketQuery app url = do
postBuild <- getPostBuild
rec ws <- jsonWebSocket url $ def { _webSocketConfig_send = pure <$> updatedRequest }
(a, request) <- cropQueryT app $ fromMaybe mempty <$> _webSocket_recv ws
let updatedRequest = leftmost [updated request, tag (current request) postBuild]
return a
cropQueryT :: (Reflex t, MonadHold t m, MonadFix m, Query q, Additive q, Group q, Eq q)
=> QueryT t q m a
-> Event t (QueryResult q)
-> m (a, Dynamic t q)
cropQueryT app result = do
rec (a, requestPatch) <- runQueryT app croppedResult
requestUniq <- holdUniqDyn $ incrementalToDynamic requestPatch
croppedResult <- cropDyn requestUniq result
return (a, requestUniq)
cropDyn :: (Query q, MonadHold t m, Reflex t, MonadFix m) => Dynamic t q -> Event t (QueryResult q) -> m (Dynamic t (QueryResult q))
cropDyn q = foldDyn (\(q', qr) v -> crop q' (qr `mappend` v)) mempty . attach (current q)