1{-# LANGUAGE ForeignFunctionInterface, JavaScriptFFI, CPP, TemplateHaskell, NoMonomorphismRestriction, EmptyDataDecls, RankNTypes, GADTs, RecursiveDo, ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses, TypeFamilies, FlexibleContexts, DeriveDataTypeable, GeneralizedNewtypeDeriving, StandaloneDeriving, ConstraintKinds, UndecidableInstances, PolyKinds, AllowAmbiguousTypes #-}
3module Reflex.Dom.WebSocket where
5import Prelude hiding (div, span, mapM, mapM_, concat, concatMap, all, sequence)
8import Reflex.Host.Class
10import Reflex.Dom.WebSocket.Foreign
12import Control.Concurrent
14import Control.Monad hiding (forM, forM_, mapM, mapM_, sequence)
15import Control.Monad.IO.Class
16import Control.Monad.Ref
17import Control.Monad.State
18import Data.ByteString (ByteString)
20import Data.Dependent.Map (DSum (..))
24 = WebSocketConfig { _webSocketConfig_send :: Event t [ByteString]
27instance Reflex t => Default (WebSocketConfig t) where
28 def = WebSocketConfig never
31 = WebSocket { _webSocket_recv :: Event t ByteString
32 , _webSocket_open :: Event t ()
35webSocket :: forall t m. (HasWebView m, MonadWidget t m) => String -> WebSocketConfig t -> m (WebSocket t)
36webSocket url config = do
39 runWithActions <- askRunWithActions
40 (eRecv, eRecvTriggerRef) <- newEventWithTriggerRef
41 currentSocketRef <- liftIO $ newIORef Nothing
42 --TODO: Disconnect if value no longer needed
43 (eOpen, eOpenTriggerRef) <- newEventWithTriggerRef
44 let onMessage :: ByteString -> IO ()
45 onMessage m = postGui $ do
46 mt <- readRef eRecvTriggerRef
47 forM_ mt $ \t -> runWithActions [t :=> Identity m]
49 mt <- readRef eOpenTriggerRef
50 forM_ mt $ \t -> runWithActions [t :=> Identity ()]
52 ws <- liftIO $ newWebSocket wv url onMessage onOpen $ do
53 void $ forkIO $ do --TODO: Is the fork necessary, or do event handlers run in their own threads automatically?
54 liftIO $ writeIORef currentSocketRef Nothing
55 liftIO $ threadDelay 1000000
57 liftIO $ writeIORef currentSocketRef $ Just ws
59 schedulePostBuild $ liftIO start
60 performEvent_ $ ffor (_webSocketConfig_send config) $ \payloads -> forM_ payloads $ \payload -> do
61 mws <- liftIO $ readIORef currentSocketRef
63 Nothing -> return () -- Discard --TODO: should we do something better here? probably buffer it, since we handle reconnection logic; how do we verify that the server has received things?
65 liftIO $ webSocketSend ws payload
66 return $ WebSocket eRecv eOpen
68makeLensesWith (lensRules & simpleLenses .~ True) ''WebSocketConfig
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