Created
October 12, 2014 12:35
-
-
Save anonymous/2b0c0aebd56a7c4fa0be to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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