keter/incoming/websockets/chat.hs
2014-12-19 16:21:07 -06:00

94 lines
2.8 KiB
Haskell

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
import Control.Concurrent (threadDelay)
import Control.Concurrent.STM.Lifted
import Control.Monad (forever)
import Control.Monad.Trans.Reader
import Data.Conduit
import qualified Data.Conduit.List as CL
import Data.Monoid ((<>))
import Data.Text (Text)
import qualified Data.Text.Lazy as TL
import Data.Time
import Yesod.Core
import Yesod.WebSockets
data App = App (TChan Text)
instance Yesod App
mkYesod "App" [parseRoutes|
/ HomeR GET
|]
chatApp :: WebSocketsT Handler ()
chatApp = do
sendTextData ("Welcome to the chat server, please enter your name." :: Text)
name <- receiveData
sendTextData $ "Welcome, " <> name
App writeChan <- getYesod
readChan <- atomically $ do
writeTChan writeChan $ name <> " has joined the chat"
dupTChan writeChan
race_
(forever $ atomically (readTChan readChan) >>= sendTextData)
(sourceWS $$ CL.mapM_ (\msg ->
atomically $ writeTChan writeChan $ name <> ": " <> msg))
getHomeR :: Handler Html
getHomeR = do
webSockets chatApp
defaultLayout $ do
[whamlet|
<div #output>
<form #form>
<input #input autofocus>
|]
toWidget [lucius|
\#output {
width: 600px;
height: 400px;
border: 1px solid black;
margin-bottom: 1em;
p {
margin: 0 0 0.5em 0;
padding: 0 0 0.5em 0;
border-bottom: 1px dashed #99aa99;
}
}
\#input {
width: 600px;
display: block;
}
|]
toWidget [julius|
var url = document.URL,
output = document.getElementById("output"),
form = document.getElementById("form"),
input = document.getElementById("input"),
conn;
url = url.replace("http:", "ws:").replace("https:", "wss:");
conn = new WebSocket(url);
conn.onmessage = function(e) {
var p = document.createElement("p");
p.appendChild(document.createTextNode(e.data));
output.appendChild(p);
};
form.addEventListener("submit", function(e){
conn.send(input.value);
input.value = "";
e.preventDefault();
});
|]
main :: IO ()
main = do
chan <- atomically newBroadcastTChan
warpEnv $ App chan