{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
module Miso.Reload
(
reload
, live
) where
import Control.Monad
#if __GLASGOW_HASKELL__ > 865
import GHC.Conc.Sync (threadLabel)
import GHC.Conc (listThreads, killThread)
#endif
#ifdef WASM
import Miso.DSL.TH.File (evalFile)
#endif
import Miso.DSL ((!), jsg, setField)
import qualified Miso.FFI.Internal as FFI
import Miso.Types (Component(..), Events, App)
import Miso.String (MisoString)
import Miso.Runtime (componentModel, initComponent, topLevelComponentId, resetComponentState, Hydrate(..))
import Miso.Runtime.Internal (components)
import Miso.Lens
import qualified Data.IntMap.Strict as IM
import Data.IORef
import Foreign hiding (void)
import Foreign.C.Types
foreign import ccall unsafe "x_store"
x_store :: StablePtr a -> IO ()
foreign import ccall unsafe "x_get"
x_get :: IO (StablePtr a)
foreign import ccall unsafe "x_exists"
x_exists :: IO CInt
foreign import ccall unsafe "x_clear"
x_clear :: IO ()
#define MISO_JS_PATH "js/miso.js"
reload
:: Eq model
=> Events
-> App model action
-> IO ()
reload :: forall model action.
Eq model =>
Events -> App model action -> IO ()
reload Events
events App model action
vcomp = do
#ifdef WASM
$(evalFile MISO_JS_PATH)
#endif
IO () -> IO ()
resetComponentState IO ()
clearPage
#if __GLASGOW_HASKELL__ > 865
threads <- IO [ThreadId]
listThreads
forM_ threads $ \ThreadId
threadId -> do
ThreadId -> IO (Maybe String)
threadLabel ThreadId
threadId IO (Maybe String) -> (Maybe String -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Just String
"scheduler" ->
ThreadId -> IO ()
killThread ThreadId
threadId
Maybe String
_ -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
#endif
initComponent events Draw vcomp
live
:: Eq model
=> Events
-> App model action
-> IO ()
live :: forall model action.
Eq model =>
Events -> App model action -> IO ()
live Events
events App model action
vcomp = do
exists <- IO CInt
x_exists
if exists == 1
then do
#if __GLASGOW_HASKELL__ > 865
threads <- listThreads
forM_ threads $ \ThreadId
threadId -> do
ThreadId -> IO (Maybe String)
threadLabel ThreadId
threadId IO (Maybe String) -> (Maybe String -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Just String
"scheduler" ->
ThreadId -> IO ()
killThread ThreadId
threadId
Maybe String
_ -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
#endif
clearPage
_oldState <- readIORef =<< deRefStablePtr =<< x_get
let oldModel = (IntMap (ComponentState (ZonkAny 0) model (ZonkAny 1))
_oldState IntMap (ComponentState (ZonkAny 0) model (ZonkAny 1))
-> Key -> ComponentState (ZonkAny 0) model (ZonkAny 1)
forall a. IntMap a -> Key -> a
IM.! Key
topLevelComponentId) ComponentState (ZonkAny 0) model (ZonkAny 1)
-> Lens (ComponentState (ZonkAny 0) model (ZonkAny 1)) model
-> model
forall record field. record -> Lens record field -> field
^. Lens (ComponentState (ZonkAny 0) model (ZonkAny 1)) model
forall parent model action.
Lens (ComponentState parent model action) model
componentModel
initialVComp = App model action
vcomp { model = oldModel }
atomicWriteIORef components _oldState
initComponent events Draw initialVComp
FFI.flush
x_clear
x_store =<< newStablePtr components
else do
#ifdef WASM
$(evalFile MISO_JS_PATH)
#endif
x_store =<< newStablePtr components
void (initComponent events Draw vcomp)
clearPage :: IO ()
clearPage :: IO ()
clearPage = do
body_ <- MisoString -> IO JSVal
jsg MisoString
"document" IO JSVal -> MisoString -> IO JSVal
forall o. ToObject o => o -> MisoString -> IO JSVal
! (MisoString
"body" :: MisoString)
setField body_ "innerHTML" ("" :: MisoString)
head_ <- jsg "document" ! ("head" :: MisoString)
setField head_ "innerHTML" ("" :: MisoString)