{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Miso.Reload
(
reload
, reloadWithContext
, live
, liveWithContext
) where
import Control.Concurrent
import Control.Monad
import Miso.DSL ((!), jsg, setField)
import qualified Miso.FFI.Internal as FFI
import Miso.Types (Component(..), Events)
import Miso.String (MisoString)
import Miso.Runtime (componentModel, initComponent, topLevelComponentId, globalContext, Hydrate(..))
import Miso.Runtime.Internal (components, schedulerThread)
import Miso.Lens
import qualified Data.IntMap.Strict as IM
import Data.IORef
import Foreign hiding (void)
import Foreign.C.Types
#ifdef NATIVE
import Miso.JSON
#endif
foreign import ccall unsafe "miso_x_store"
x_store :: StablePtr a -> IO ()
foreign import ccall unsafe "miso_x_get"
x_get :: IO (StablePtr a)
foreign import ccall unsafe "miso_x_exists"
x_exists :: IO CInt
foreign import ccall unsafe "miso_x_clear"
x_clear :: IO ()
#define MISO_JS_PATH "js/miso.js"
reload
#ifdef NATIVE
:: (FromJSON action, ToJSON model, ToJSON action, Eq model)
#else
:: (Eq model)
#endif
=> Events
-> Component () () model action
-> IO ()
reload :: forall model action.
Eq model =>
Events -> Component () () model action -> IO ()
reload Events
events = Events -> () -> Component () () model action -> IO ()
forall context model action.
(Eq context, Eq model) =>
Events -> context -> Component context () model action -> IO ()
reloadWithContext Events
events ()
reloadWithContext
#ifdef NATIVE
:: (FromJSON action, ToJSON model, Eq context, Eq model, ToJSON action)
#else
:: (Eq context, Eq model)
#endif
=> Events
-> context
-> Component context () model action
-> IO ()
reloadWithContext :: forall context model action.
(Eq context, Eq model) =>
Events -> context -> Component context () model action -> IO ()
reloadWithContext Events
events context
initialContext Component context () model action
comp = do
CInt
exists <- IO CInt
x_exists
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
exists CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
(Any
_, IORef ThreadId
oldSchedulerRef, Any
_) <- StablePtr (Any, IORef ThreadId, Any)
-> IO (Any, IORef ThreadId, Any)
forall a. StablePtr a -> IO a
deRefStablePtr (StablePtr (Any, IORef ThreadId, Any)
-> IO (Any, IORef ThreadId, Any))
-> IO (StablePtr (Any, IORef ThreadId, Any))
-> IO (Any, IORef ThreadId, Any)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (StablePtr (Any, IORef ThreadId, Any))
forall a. IO (StablePtr a)
x_get
ThreadId -> IO ()
killThread (ThreadId -> IO ()) -> IO ThreadId -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IORef ThreadId -> IO ThreadId
forall a. IORef a -> IO a
readIORef IORef ThreadId
oldSchedulerRef
IO ()
x_clear
IO ()
clearPage
IO () -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Events
-> Hydrate
-> Bool
-> context
-> Component context () model action
-> Maybe Key
-> ()
-> Maybe StaticKey
-> IO ()
forall context props model action.
(Eq context, Eq model, Eq props) =>
Events
-> Hydrate
-> Bool
-> context
-> Component context props model action
-> Maybe Key
-> props
-> Maybe StaticKey
-> IO ()
initComponent Events
events Hydrate
Draw Bool
False context
initialContext Component context () model action
comp Maybe Key
forall a. Maybe a
Nothing () Maybe StaticKey
forall a. Maybe a
Nothing)
StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any)
-> IO ()
forall a. StablePtr a -> IO ()
x_store (StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any)
-> IO ())
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any))
-> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any)
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any))
forall a. a -> IO (StablePtr a)
newStablePtr (IORef (IntMap (ComponentState Any Any Any Any))
forall context props model action.
IORef (IntMap (ComponentState context props model action))
components, IORef ThreadId
schedulerThread, IORef context
forall {context}. IORef context
globalContext :: IORef context)
live
#ifdef NATIVE
:: (Eq model, ToJSON model, ToJSON action, FromJSON action)
#else
:: Eq model
#endif
=> Events
-> Component () () model action
-> IO ()
live :: forall model action.
Eq model =>
Events -> Component () () model action -> IO ()
live Events
events Component () () model action
vcomp_ = Events -> () -> Component () () model action -> IO ()
forall context model action.
(Eq context, Eq model) =>
Events -> context -> Component context () model action -> IO ()
liveWithContext Events
events () Component () () model action
vcomp_
liveWithContext
#ifdef NATIVE
:: (Eq context, Eq model, ToJSON model, ToJSON action, FromJSON action)
#else
:: (Eq context, Eq model)
#endif
=> Events
-> context
-> Component context () model action
-> IO ()
liveWithContext :: forall context model action.
(Eq context, Eq model) =>
Events -> context -> Component context () model action -> IO ()
liveWithContext Events
events context
initialContext Component context () model action
vcomp_ = do
CInt
exists <- IO CInt
x_exists
if CInt
exists CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1
then do
IO ()
clearBody
(IORef (IntMap (ComponentState Any Any model Any))
oldComponentsRef, IORef ThreadId
oldSchedulerRef, IORef context
oldContextRef) <- StablePtr
(IORef (IntMap (ComponentState Any Any model Any)), IORef ThreadId,
IORef context)
-> IO
(IORef (IntMap (ComponentState Any Any model Any)), IORef ThreadId,
IORef context)
forall a. StablePtr a -> IO a
deRefStablePtr (StablePtr
(IORef (IntMap (ComponentState Any Any model Any)), IORef ThreadId,
IORef context)
-> IO
(IORef (IntMap (ComponentState Any Any model Any)), IORef ThreadId,
IORef context))
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any model Any)), IORef ThreadId,
IORef context))
-> IO
(IORef (IntMap (ComponentState Any Any model Any)), IORef ThreadId,
IORef context)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO
(StablePtr
(IORef (IntMap (ComponentState Any Any model Any)), IORef ThreadId,
IORef context))
forall a. IO (StablePtr a)
x_get
context
oldContext <- IORef context -> IO context
forall a. IORef a -> IO a
readIORef IORef context
oldContextRef
ThreadId -> IO ()
killThread (ThreadId -> IO ()) -> IO ThreadId -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IORef ThreadId -> IO ThreadId
forall a. IORef a -> IO a
readIORef IORef ThreadId
oldSchedulerRef
IntMap (ComponentState Any Any model Any)
_oldState <- IORef (IntMap (ComponentState Any Any model Any))
-> IO (IntMap (ComponentState Any Any model Any))
forall a. IORef a -> IO a
readIORef IORef (IntMap (ComponentState Any Any model Any))
oldComponentsRef
let oldModel :: model
oldModel = (IntMap (ComponentState Any Any model Any)
_oldState IntMap (ComponentState Any Any model Any)
-> Key -> ComponentState Any Any model Any
forall a. IntMap a -> Key -> a
IM.! Key
topLevelComponentId) ComponentState Any Any model Any
-> Lens (ComponentState Any Any model Any) model -> model
forall record field. record -> Lens record field -> field
^. Lens (ComponentState Any Any model Any) model
forall context props model action.
Lens (ComponentState context props model action) model
componentModel
initialVComp :: Component context () model action
initialVComp = Component context () model action
vcomp_ { model = oldModel }
IORef (IntMap (ComponentState Any Any model Any))
-> IntMap (ComponentState Any Any model Any) -> IO ()
forall a. IORef a -> a -> IO ()
atomicWriteIORef IORef (IntMap (ComponentState Any Any model Any))
forall context props model action.
IORef (IntMap (ComponentState context props model action))
components IntMap (ComponentState Any Any model Any)
_oldState
Events
-> Hydrate
-> Bool
-> context
-> Component context () model action
-> Maybe Key
-> ()
-> Maybe StaticKey
-> IO ()
forall context props model action.
(Eq context, Eq model, Eq props) =>
Events
-> Hydrate
-> Bool
-> context
-> Component context props model action
-> Maybe Key
-> props
-> Maybe StaticKey
-> IO ()
initComponent Events
events Hydrate
Draw Bool
True context
oldContext Component context () model action
initialVComp Maybe Key
forall a. Maybe a
Nothing () Maybe StaticKey
forall a. Maybe a
Nothing
IO ()
FFI.flush
IO ()
x_clear
StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any)
-> IO ()
forall a. StablePtr a -> IO ()
x_store (StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any)
-> IO ())
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any))
-> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any)
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any))
forall a. a -> IO (StablePtr a)
newStablePtr (IORef (IntMap (ComponentState Any Any Any Any))
forall context props model action.
IORef (IntMap (ComponentState context props model action))
components, IORef ThreadId
schedulerThread, IORef context
forall {context}. IORef context
globalContext :: IORef context)
else do
IO () -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Events
-> Hydrate
-> Bool
-> context
-> Component context () model action
-> Maybe Key
-> ()
-> Maybe StaticKey
-> IO ()
forall context props model action.
(Eq context, Eq model, Eq props) =>
Events
-> Hydrate
-> Bool
-> context
-> Component context props model action
-> Maybe Key
-> props
-> Maybe StaticKey
-> IO ()
initComponent Events
events Hydrate
Draw Bool
False context
initialContext Component context () model action
vcomp_ Maybe Key
forall a. Maybe a
Nothing () Maybe StaticKey
forall a. Maybe a
Nothing)
StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any)
-> IO ()
forall a. StablePtr a -> IO ()
x_store (StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any)
-> IO ())
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any))
-> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any)
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId,
IORef Any))
forall a. a -> IO (StablePtr a)
newStablePtr (IORef (IntMap (ComponentState Any Any Any Any))
forall context props model action.
IORef (IntMap (ComponentState context props model action))
components, IORef ThreadId
schedulerThread, IORef context
forall {context}. IORef context
globalContext :: IORef context)
clearPage, clearBody, clearHead :: IO ()
clearPage :: IO ()
clearPage = IO ()
clearBody IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
clearHead
clearBody :: IO ()
clearBody = do
JSVal
body_ <- MisoString -> IO JSVal
jsg MisoString
"document" IO JSVal -> MisoString -> IO JSVal
forall o. ToObject o => o -> MisoString -> IO JSVal
! (MisoString
"body" :: MisoString)
JSVal -> MisoString -> MisoString -> IO ()
forall o v.
(ToObject o, ToJSVal v) =>
o -> MisoString -> v -> IO ()
setField JSVal
body_ MisoString
"innerHTML" (MisoString
"" :: MisoString)
clearHead :: IO ()
clearHead = do
JSVal
head_ <- MisoString -> IO JSVal
jsg MisoString
"document" IO JSVal -> MisoString -> IO JSVal
forall o. ToObject o => o -> MisoString -> IO JSVal
! (MisoString
"head" :: MisoString)
JSVal -> MisoString -> MisoString -> IO ()
forall o v.
(ToObject o, ToJSVal v) =>
o -> MisoString -> v -> IO ()
setField JSVal
head_ MisoString
"innerHTML" (MisoString
"" :: MisoString)