{-# LANGUAGE TemplateHaskell #-}
module IHP.ServerSideComponent.ControllerFunctions where
import IHP.Prelude
import IHP.ControllerPrelude
import IHP.ServerSideComponent.Types as SSC
import qualified Network.WebSockets as WebSocket
import qualified Text.Blaze.Html.Renderer.Text as Blaze
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.TH as Aeson
import IHP.ServerSideComponent.HtmlParser
import IHP.ServerSideComponent.HtmlDiff
$(Aeson.deriveJSON Aeson.defaultOptions { sumEncoding = defaultTaggedObject { tagFieldName = "type" }} ''Attribute)
$(Aeson.deriveJSON Aeson.defaultOptions { sumEncoding = defaultTaggedObject { tagFieldName = "type" }} ''AttributeOperation)
$(Aeson.deriveJSON Aeson.defaultOptions { sumEncoding = defaultTaggedObject { tagFieldName = "type" }} ''Node)
$(Aeson.deriveJSON Aeson.defaultOptions { sumEncoding = defaultTaggedObject { tagFieldName = "type" }} ''NodeOperation)
setState :: (?instanceRef :: IORef (ComponentInstance state), ?connection :: WebSocket.Connection, Component state action, ?context :: ControllerContext) => state -> IO ()
setState :: forall state action.
(?instanceRef::IORef (ComponentInstance state),
?connection::Connection, Component state action,
?context::ControllerContext) =>
state -> IO ()
setState state
state = do
state
oldState <- (.state) (ComponentInstance state -> state)
-> IO (ComponentInstance state) -> IO state
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef (ComponentInstance state) -> IO (ComponentInstance state)
forall a. IORef a -> IO a
readIORef ?instanceRef::IORef (ComponentInstance state)
IORef (ComponentInstance state)
?instanceRef
let oldHtml :: Text
oldHtml = state
oldState
state -> (state -> Html) -> Html
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> state -> Html
state -> Html
forall state action. Component state action => state -> Html
SSC.render
Html -> (Html -> Text) -> Text
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> Html -> Text
Blaze.renderHtml
Text -> (Text -> Text) -> Text
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> Text -> Text
forall a b. ConvertibleStrings a b => a -> b
cs
let newHtml :: Text
newHtml = state
state
state -> (state -> Html) -> Html
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> state -> Html
state -> Html
forall state action. Component state action => state -> Html
SSC.render
Html -> (Html -> Text) -> Text
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> Html -> Text
Blaze.renderHtml
Text -> (Text -> Text) -> Text
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> Text -> Text
forall a b. ConvertibleStrings a b => a -> b
cs
IORef (ComponentInstance state)
-> (ComponentInstance state -> ComponentInstance state) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' ?instanceRef::IORef (ComponentInstance state)
IORef (ComponentInstance state)
?instanceRef (\ComponentInstance state
componentInstance -> ComponentInstance state
componentInstance { state
state :: state
$sel:state:ComponentInstance :: state
state })
case Text -> Text -> Either (ParseErrorBundle Text Void) [NodeOperation]
diffHtml Text
oldHtml Text
newHtml of
Left ParseErrorBundle Text Void
error -> Text -> IO ()
putStrLn (ParseErrorBundle Text Void -> Text
forall a. Show a => a -> Text
tshow ParseErrorBundle Text Void
error)
Right [NodeOperation]
patches -> ByteString -> IO ()
forall text.
(?connection::Connection, WebSocketsData text) =>
text -> IO ()
sendTextData ([NodeOperation] -> ByteString
forall a. ToJSON a => a -> ByteString
Aeson.encode [NodeOperation]
patches)
getState :: (?instanceRef :: IORef (ComponentInstance state)) => IO state
getState :: forall state.
(?instanceRef::IORef (ComponentInstance state)) =>
IO state
getState = (.state) (ComponentInstance state -> state)
-> IO (ComponentInstance state) -> IO state
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef (ComponentInstance state) -> IO (ComponentInstance state)
forall a. IORef a -> IO a
readIORef ?instanceRef::IORef (ComponentInstance state)
IORef (ComponentInstance state)
?instanceRef
deriveSSC :: Name -> Q [Dec]
deriveSSC = Options -> Name -> Q [Dec]
Aeson.deriveJSON Options
Aeson.defaultOptions { allNullaryToStringTag :: Bool
allNullaryToStringTag = Bool
False, sumEncoding :: SumEncoding
sumEncoding = SumEncoding
defaultTaggedObject { tagFieldName :: String
tagFieldName = String
"action", contentsFieldName :: String
contentsFieldName = String
"payload" }}