{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RebindableSyntax #-} module WebSockets where import Data.Text import FFI -- | WebSocket object to keep connection, handle events and sending data. data WebSocket -- | WebSocket event. data WSEvent -- | State of WebSocket data WSState = Connecting | Open | Closing | Closed -- | Get current url and replace 'http' with 'ws'. getWsUrl :: Fay Text getWsUrl = ffi "window['location']['href'].replace('http:', 'ws:').replace('https:', 'wss:')" -- | Wrapper over '.onopen' event. onOpen :: WSEvent -> Fay () onOpen = ffi "console.log('WebSocket is up and running')" -- | Wrapper over '.onclose' event. onClose :: WebSocket -> Fay f -> Fay () onClose = ffi "%1.onclose=%2" -- | Wrapper over '.onError' event. onError :: WebSocket -> Fay f -> Fay () onError = ffi "%1.onerror=%2" -- | Get text data from event. eventData :: WSEvent -> Fay Text eventData = ffi "%1['data']" -- | Wrapper over '.onMessage' onMessage :: WSEvent -> Fay () onMessage = ffi "(function(e){console.log(e); console.log(e.data);})(%1)" -- | Key function that by given URL initialize connection, starts to listen all events and ready to sending data. websocket :: Text -- ^ WebSocket endpoint URL; -> (WSEvent -> Fay ()) -- ^ when connection opened ; -> (WSEvent -> Fay ()) -- ^ when messages received; -> (WSEvent -> Fay ()) -- ^ when errors occured; -> (WSEvent -> Fay ()) -- ^ when connection closed. -> Fay WebSocket websocket = ffi "(function (){var conn = new WebSocket(%1);\ \ conn.onopen = %2, conn.onmessage = %3, conn.onerror = %4, conn.onclose = %5;\ \return conn})()" -- FIXME: add 'USVString', 'ArrayBuffer', 'Blob', 'ArrayBufferView' -- | Send text data over WebSocket. sendWS :: WebSocket -> Text -> Fay () sendWS = ffi "%1.send(%2)" -- | Close current connection. close :: WebSocket -> Fay () close = ffi "%1.close"