Skip to content

Instantly share code, notes, and snippets.

Created October 12, 2014 12:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/2b0c0aebd56a7c4fa0be to your computer and use it in GitHub Desktop.
Save anonymous/2b0c0aebd56a7c4fa0be to your computer and use it in GitHub Desktop.
(ns hendrix.core
(:require-macros [cljs.core.async.macros :refer [go]])
(:require [cljs.core.async :refer [put! chan <!]]
[om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[secretary.core :as secretary :include-macros true :refer [defroute]]
[goog.events :as events]
[goog.history.EventType :as EventType])
(:import goog.History))
(enable-console-print!)
(defn log [x]
(.log js/console x))
(defn from-store [k]
(.get js/store k))
(defn to-store [k v]
(.set js/store k v))
(defn connect-to-peerserver
([peer-id]
(connect-to-peerserver peer-id {:host "localhost" :port 9000}))
([peer-id options]
(println "connecting to peerserver as" peer-id)
(js/Peer. peer-id (clj->js options))))
(defn connection->peer-id [connection]
(.-peer connection))
(defn new-connection [peer peer-id]
(println "connecting to" peer-id)
(.connect peer peer-id))
(defn send-data [connection data]
(println "sending" (:text data) "to" (connection->peer-id connection) "as" (:author data))
(.send connection (clj->js data)))
(defn get-peer-id []
(re-find #"\w+" (.. js/window -location -hash)))
(defn build-message [author text]
{:author author :text text})
(def app-state
(atom {:peer-id nil
:peer nil
:connections []
:room-name "developerslv"
:messages []}))
(defn message-component [message owner]
(reify
om/IRender
(render [_]
(dom/tr nil
(dom/td #js {:className "author"} (:author message))
(dom/td #js {:className "message"} (:text message))))))
(defn messages-component [app owner]
(reify
om/IRender
(render [_]
(dom/div #js {:id "messages-wrapper"}
(dom/div #js {:id "messages"}
(dom/table nil
(apply dom/tbody nil
(om/build-all message-component (:messages app)))))))))
(defn enter-pressed? [event]
(= (.-key event) "Enter"))
(defn on-change [event chat-box]
(om/set-state! chat-box :text (.. event -target -value)))
(defn on-key-up [event app owner state]
(let [text (:text state)]
(when (and (enter-pressed? event) (not (empty? text)))
(om/transact! app :messages #(conj % (build-message (:peer-id @app) text)))
(om/set-state! owner :text "")
(let [send-message (:send-message state)]
(send-message (build-message (:peer-id @app) text))))))
(defn textarea-component [app owner]
(reify
om/IInitState
(init-state [_]
{:text ""})
om/IRenderState
(render-state [_ state]
(dom/div #js {:id "message-box"}
(dom/textarea #js {:value (:text state)
:onChange #(on-change % owner)
:onKeyUp #(on-key-up % app owner state)})
(dom/div #js {:id "markdown-mark"})))))
(defn send-message [message connections]
(doseq [connection connections]
(send-data connection message)))
(defn root-component [app owner]
(reify
om/IInitState
(init-state [_]
{:new-connection-chan (chan)
:new-data-chan (chan)})
om/IWillMount
(will-mount [_]
(let [peer-id (from-store "author")
peer (connect-to-peerserver peer-id)
new-connection-chan (om/get-state owner :new-connection-chan)
new-data-chan (om/get-state owner :new-data-chan)]
(om/update! app [:peer-id] peer-id)
(om/update! app [:peer] peer)
(go (loop []
(let [connection (<! new-connection-chan)
peer-id (connection->peer-id connection)]
(println (str "new connection from " (connection->peer-id connection)))
(om/transact! app :connections #(conj % connection))
(.on connection "error" #(.error js/console %))
(.on connection "data" #(put! new-data-chan %))
(recur))))
(go (loop []
(let [data (<! new-data-chan)
message (js->clj data :keywordize-keys true)]
(println "received" (:text message) "from" (:author message))
(om/transact! app :messages
#(conj % message))
(recur))))
(println "listening for new connections")
(.on peer "connection" #(put! new-connection-chan %))
(let [peer-id-to-other (re-find #"\w+" (.. js/window -location -hash))]
(if (not (empty? peer-id-to-other))
(let [connection (new-connection peer peer-id-to-other)]
(.on connection "error" #(.error js/console %))
(.on connection "data" #(put! new-data-chan %))
(om/transact! app :connections #(conj % connection)))
(set! (.. js/window -location -hash) (str "/" peer-id))))))
om/IRenderState
(render-state [_ state]
(dom/div nil
(dom/nav #js {:id "nav"}
(dom/ul nil
(dom/li #js {:id "burger" :className "fa fa-bars"})))
(dom/div #js {:id "content"}
(dom/div #js {:id "chat-box"}
(dom/h1 nil (dom/a #js {:href "/"} (:room-name app)))
(om/build messages-component app)
(om/build textarea-component app
{:init-state
{:send-message
#(send-message % (:connections @app))}})))))))
(om/root
root-component
app-state
{:target (. js/document (getElementById "app"))})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment