1{-# LANGUAGE ConstraintKinds #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE LambdaCase #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE NoMonomorphismRestriction #-}
8{-# LANGUAGE RankNTypes #-}
9{-# LANGUAGE RecursiveDo #-}
10{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE TypeFamilies #-}
12{-# LANGUAGE TypeOperators #-}
13{-# LANGUAGE UndecidableInstances #-}
14module Reflex.Dom.Internal where
16import Prelude hiding (concat, mapM, mapM_, sequence, sequence_)
18import qualified Reflex as R
19import Reflex.Dom.Builder.Immediate
20import Reflex.Dom.Class
21import Reflex.Dom.Internal.Foreign
22import Reflex.Host.Class
23import Reflex.PerformEvent.Base
24import Reflex.PostBuild.Base
25import Reflex.Spider (Global, Spider, SpiderHost, runSpiderHost)
26import Reflex.TriggerEvent.Base
28import Control.Concurrent
31import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
32import Control.Monad.Ref
33import Data.ByteString (ByteString)
34import Data.Dependent.Sum (DSum (..))
37import Data.Monoid ((<>))
38import Data.Text (Text)
39import qualified Data.Text as T
40import Data.Text.Encoding
41import GHCJS.DOM hiding (runWebGUI)
42import GHCJS.DOM.Document
43import GHCJS.DOM.Element
45import qualified GHCJS.DOM.Types as DOM
47{-# INLINABLE mainWidget #-}
48mainWidget :: (forall x. Widget x ()) -> IO ()
49mainWidget w = runWebGUI $ \webView -> withWebViewSingleton webView $ \webViewSing -> do
50 Just doc <- fmap DOM.castToHTMLDocument <$> webViewGetDomDocument webView
51 Just body <- getBody doc
52 attachWidget body webViewSing w
54--TODO: The x's should be unified here
55{-# INLINABLE mainWidgetWithHead #-}
56mainWidgetWithHead :: (forall x. Widget x ()) -> (forall x. Widget x ()) -> IO ()
57mainWidgetWithHead h b = runWebGUI $ \webView -> withWebViewSingleton webView $ \webViewSing -> do
58 Just doc <- fmap DOM.castToHTMLDocument <$> webViewGetDomDocument webView
59 Just headElement <- fmap DOM.castToHTMLElement <$> getHead doc
60 attachWidget headElement webViewSing h
61 Just body <- getBody doc
62 attachWidget body webViewSing b
64{-# INLINABLE mainWidgetWithCss #-}
65mainWidgetWithCss :: ByteString -> (forall x. Widget x ()) -> IO ()
66mainWidgetWithCss css w = runWebGUI $ \webView -> withWebViewSingleton webView $ \webViewSing -> do
67 Just doc <- fmap DOM.castToHTMLDocument <$> webViewGetDomDocument webView
68 Just headElement <- fmap DOM.castToHTMLElement <$> getHead doc
69 setInnerHTML headElement . Just $ "<style>" <> T.unpack (decodeUtf8 css) <> "</style>" --TODO: Fix this
70 Just body <- getBody doc
71 attachWidget body webViewSing w
73type Widget x = PostBuildT Spider (ImmediateDomBuilderT Spider (WithWebView x (PerformEventT Spider (SpiderHost Global)))) --TODO: Make this more abstract --TODO: Put the WithWebView underneath PerformEventT - I think this would perform better
75{-# INLINABLE attachWidget #-}
76attachWidget :: DOM.IsElement e => e -> WebViewSingleton x -> Widget x a -> IO a
77attachWidget rootElement wv w = fst <$> attachWidget' rootElement wv w
79mainWidgetWithHead' :: (forall x. (a -> Widget x b, b -> Widget x a)) -> IO ()
80mainWidgetWithHead' widgets = runWebGUI $ \webView -> withWebViewSingleton webView $ \wv -> fmap fst $ attachWidget'' $ \events -> do
81 let (headWidget, bodyWidget) = widgets
82 Just doc <- liftIO $ fmap DOM.castToHTMLDocument <$> webViewGetDomDocument webView
83 Just headElement <- getHead doc
84 Just bodyElement <- getBody doc
85 (postBuild, postBuildTriggerRef) <- newEventWithTriggerRef
86 rec b <- unsafeReplaceElementContentsWithWidget events postBuild headElement wv $ headWidget a
87 a <- unsafeReplaceElementContentsWithWidget events postBuild bodyElement wv $ bodyWidget b
88 return ((), postBuildTriggerRef)
90unsafeReplaceElementContentsWithWidget :: DOM.IsElement e => EventChannel -> R.Event Spider () -> e -> WebViewSingleton x -> Widget x a -> PerformEventT Spider (SpiderHost Global) a
91unsafeReplaceElementContentsWithWidget events postBuild rootElement wv w = do
92 Just doc <- getOwnerDocument rootElement
93 Just df <- createDocumentFragment doc
94 let builderEnv = ImmediateDomBuilderEnv
95 { _immediateDomBuilderEnv_document = doc
96 , _immediateDomBuilderEnv_parent = toNode df
97 , _immediateDomBuilderEnv_events = events
99 result <- runWithWebView (runImmediateDomBuilderT (runPostBuildT w postBuild) builderEnv) wv
100 setInnerHTML rootElement $ Just ("" :: String)
101 _ <- appendChild rootElement $ Just df
104{-# INLINABLE attachWidget' #-}
105attachWidget' :: DOM.IsElement e => e -> WebViewSingleton x -> Widget x a -> IO (a, FireCommand Spider (SpiderHost Global))
106attachWidget' rootElement wv w = attachWidget'' $ \events -> do
107 (postBuild, postBuildTriggerRef) <- newEventWithTriggerRef
108 result <- unsafeReplaceElementContentsWithWidget events postBuild rootElement wv w
109 return (result, postBuildTriggerRef)
111type EventChannel = Chan [DSum (TriggerRef Spider) TriggerInvocation]
113{-# INLINABLE attachWidget'' #-}
114attachWidget'' :: (EventChannel -> PerformEventT Spider (SpiderHost Global) (a, IORef (Maybe (EventTrigger Spider ())))) -> IO (a, FireCommand Spider (SpiderHost Global))
117 (result, fc@(FireCommand fire)) <- runSpiderHost $ do
118 ((result, postBuildTriggerRef), fc@(FireCommand fire)) <- hostPerformEventT $ w events
119 mPostBuildTrigger <- readRef postBuildTriggerRef
120 forM_ mPostBuildTrigger $ \postBuildTrigger -> fire [postBuildTrigger :=> Identity ()] $ return ()
122 void $ forkIO $ forever $ do
123 ers <- readChan events
124 _ <- postGUISync $ runSpiderHost $ do
125 mes <- liftIO $ forM ers $ \(TriggerRef er :=> TriggerInvocation a _) -> do
127 return $ fmap (\e -> e :=> Identity a) me
128 _ <- fire (catMaybes mes) $ return ()
129 liftIO $ forM_ ers $ \(_ :=> TriggerInvocation _ cb) -> cb
133-- | Run a reflex-dom application inside of an existing DOM element with the given ID
134mainWidgetInElementById :: Text -> (forall x. Widget x ()) -> IO ()
135mainWidgetInElementById eid w = runWebGUI $ \webView -> withWebViewSingleton webView $ \webViewSing -> do
136 Just doc <- fmap DOM.castToHTMLDocument <$> webViewGetDomDocument webView
137 Just root <- getElementById doc eid
138 attachWidget root webViewSing w
140data AppInput t = AppInput
141 { _appInput_window :: Window t
144data AppOutput t = AppOutput --TODO: Add quit event
145 { _appOutput_windowConfig :: WindowConfig t
148runApp' :: (t ~ Spider) => (forall x. AppInput t -> Widget x (AppOutput t)) -> IO ()
149runApp' app = runWebGUI $ \webView -> withWebViewSingleton webView $ \webViewSing -> do
150 Just doc <- fmap DOM.castToHTMLDocument <$> webViewGetDomDocument webView
151 Just body <- getBody doc
152 Just win <- getDefaultView doc
153 rec o <- attachWidget body webViewSing $ do
154 w <- lift $ wrapWindow win $ _appOutput_windowConfig o
156 { _appInput_window = w
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list