{-# 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, componentContext, initComponent, topLevelComponentId, 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 action model.
(FromJSON action, ToJSON model, ToJSON action, Eq model) =>
Events -> Component () () model action -> IO ()
reload Events
events = Events -> () -> Component () () model action -> IO ()
forall action model context.
(FromJSON action, ToJSON model, Eq context, Eq model,
ToJSON action) =>
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 action model context.
(FromJSON action, ToJSON model, Eq context, Eq model,
ToJSON action) =>
Events -> context -> Component context () model action -> IO ()
reloadWithContext Events
events context
initialContext Component context () model action
comp = do
exists <- IO CInt
x_exists
when (exists == 1) $ do
(_, oldSchedulerRef) <- deRefStablePtr =<< x_get
killThread =<< readIORef oldSchedulerRef
x_clear
clearPage
void (initComponent events Draw False initialContext comp Nothing () Nothing)
x_store =<< newStablePtr (components, schedulerThread)
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, ToJSON model, ToJSON action, FromJSON action) =>
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, ToJSON model, ToJSON action,
FromJSON action) =>
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, ToJSON model, ToJSON action,
FromJSON action) =>
Events -> context -> Component context () model action -> IO ()
liveWithContext Events
events context
initialContext Component context () model action
vcomp_ = do
exists <- IO CInt
x_exists
if exists == 1
then do
clearBody
(oldComponentsRef, oldSchedulerRef) <- deRefStablePtr =<< x_get
killThread =<< readIORef oldSchedulerRef
_oldState <- readIORef oldComponentsRef
let oldModel = (IntMap (ComponentState context (ZonkAny 0) model (ZonkAny 1))
_oldState IntMap (ComponentState context (ZonkAny 0) model (ZonkAny 1))
-> Key -> ComponentState context (ZonkAny 0) model (ZonkAny 1)
forall a. IntMap a -> Key -> a
IM.! Key
topLevelComponentId) ComponentState context (ZonkAny 0) model (ZonkAny 1)
-> Lens
(ComponentState context (ZonkAny 0) model (ZonkAny 1)) model
-> model
forall record field. record -> Lens record field -> field
^. Lens (ComponentState context (ZonkAny 0) model (ZonkAny 1)) model
forall context props model action.
Lens (ComponentState context props model action) model
componentModel
initialVComp = Component context () model action
vcomp_ { model = oldModel }
oldContext <- readIORef ((_oldState IM.! topLevelComponentId) ^. componentContext)
atomicWriteIORef components _oldState
initComponent events Draw True oldContext initialVComp Nothing () Nothing
newState <- readIORef components
forM_ (IM.lookup topLevelComponentId newState) $ \ComponentState (ZonkAny 2) (ZonkAny 3) (ZonkAny 4) (ZonkAny 5)
root -> do
let newCell :: IORef (ZonkAny 2)
newCell = ComponentState (ZonkAny 2) (ZonkAny 3) (ZonkAny 4) (ZonkAny 5)
root ComponentState (ZonkAny 2) (ZonkAny 3) (ZonkAny 4) (ZonkAny 5)
-> Lens
(ComponentState (ZonkAny 2) (ZonkAny 3) (ZonkAny 4) (ZonkAny 5))
(IORef (ZonkAny 2))
-> IORef (ZonkAny 2)
forall record field. record -> Lens record field -> field
^. Lens
(ComponentState (ZonkAny 2) (ZonkAny 3) (ZonkAny 4) (ZonkAny 5))
(IORef (ZonkAny 2))
forall context props model action.
Lens (ComponentState context props model action) (IORef context)
componentContext
IORef
(IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8)))
-> (IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8))
-> (IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8)),
()))
-> IO ()
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef
(IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8)))
forall context props model action.
IORef (IntMap (ComponentState context props model action))
components ((IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8))
-> (IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8)),
()))
-> IO ())
-> (IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8))
-> (IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8)),
()))
-> IO ()
forall a b. (a -> b) -> a -> b
$ \IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8))
m ->
((ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8)
-> ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8))
-> IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8))
-> IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8))
forall a b. (a -> b) -> IntMap a -> IntMap b
IM.map (Lens
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8))
(IORef (ZonkAny 2))
forall context props model action.
Lens (ComponentState context props model action) (IORef context)
componentContext Lens
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8))
(IORef (ZonkAny 2))
-> IORef (ZonkAny 2)
-> ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8)
-> ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8)
forall record field. Lens record field -> field -> record -> record
.~ IORef (ZonkAny 2)
newCell) IntMap
(ComponentState (ZonkAny 2) (ZonkAny 6) (ZonkAny 7) (ZonkAny 8))
m, ())
FFI.flush
x_clear
x_store =<< newStablePtr (components, schedulerThread)
else do
void (initComponent events Draw False initialContext vcomp_ Nothing () Nothing)
x_store =<< newStablePtr (components, schedulerThread)
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
body_ <- Text -> IO JSVal
jsg Text
"document" IO JSVal -> Text -> IO JSVal
forall o. ToObject o => o -> Text -> IO JSVal
! (Text
"body" :: MisoString)
setField body_ "innerHTML" ("" :: MisoString)
clearHead :: IO ()
clearHead = do
head_ <- Text -> IO JSVal
jsg Text
"document" IO JSVal -> Text -> IO JSVal
forall o. ToObject o => o -> Text -> IO JSVal
! (Text
"head" :: MisoString)
setField head_ "innerHTML" ("" :: MisoString)