78 lines
3 KiB
Clojure
78 lines
3 KiB
Clojure
(ns views.reagent.sente.client
|
|
(:require
|
|
[views.reagent.client.core :as client]
|
|
[taoensso.sente :as sente]))
|
|
|
|
(defonce ^:private send-buffer (atom []))
|
|
|
|
(defn- sente-connected?
|
|
[sente-chsk-map]
|
|
(:open? @(:state sente-chsk-map)))
|
|
|
|
(defn send-fn
|
|
[sente-chsk-map data]
|
|
(if-not (sente-connected? sente-chsk-map)
|
|
(swap! send-buffer conj data)
|
|
((:send-fn sente-chsk-map) data)))
|
|
|
|
(defn- flush-send-buffer!
|
|
[sente-chsk-map]
|
|
(doseq [data @send-buffer]
|
|
(send-fn sente-chsk-map data))
|
|
(reset! send-buffer []))
|
|
|
|
(defn chsk-open-event?
|
|
"returns true if the sente event is for a channel-socket state change to 'open' or 'connected'."
|
|
[{:keys [event] :as ev}]
|
|
; for :chsk/state events, sente sends the event data in the form [old-state new-state].
|
|
; we only care about the new state for the purposes of performing this check ...
|
|
(let [[ev-id ev-data] event]
|
|
(and (= :chsk/state ev-id)
|
|
(:open? (second ev-data)))))
|
|
|
|
(defn on-open!
|
|
"should be called when a new Sente connection is established. ev is the event
|
|
map provided by Sente where id = :chsk/state, and :open? = true. make sure
|
|
to call this function on all connection open events, not just the first one."
|
|
[sente-chsk-map {:keys [event id client-id] :as ev}]
|
|
(flush-send-buffer! sente-chsk-map)
|
|
(client/on-open!))
|
|
|
|
(defn on-receive!
|
|
"should be called whenever a new message is received by Sente from the server.
|
|
ev is the event map provided by Sente where id = :chsk/recv. if this function
|
|
returns true it means the received message was for views.reagent and your
|
|
application code does not need to handle the event itself."
|
|
[sente-chsk-map {:keys [event id client-id] :as ev}]
|
|
(let [[event-id event-data] event]
|
|
(client/on-receive! event-data)))
|
|
|
|
(defn default-event-msg-handler
|
|
"very basic Sente event handler that can be used with Sente's start-chsk-router!
|
|
which makes sure on-open! and on-receive! are called when appropriate. if your
|
|
application does not need to do any custom Sente event handling, then you can
|
|
opt to use this event handler."
|
|
[sente-chsk-map {:keys [event id client-id] :as ev}]
|
|
(cond
|
|
(chsk-open-event? event)
|
|
(on-open! sente-chsk-map ev)
|
|
|
|
(= :chsk/recv id)
|
|
(on-receive! sente-chsk-map ev)))
|
|
|
|
(defn init!
|
|
"performs initial configuration necessary to hook Sente into views.reagent as the
|
|
client/server messaging backend. should be called once on page-load after the
|
|
Sente channel socket has been created (via make-channel-socket!).
|
|
|
|
extra available options specific to views.reagent/sente:
|
|
|
|
:use-default-sente-router?
|
|
- if set, enables the use of a default Sente event handler (set via Sente's
|
|
start-chsk-router!). if your application does not need to respond to any
|
|
Sente events itself, then you may wish to use this option."
|
|
[sente-chsk-map & [options]]
|
|
(reset! client/send-fn #(send-fn sente-chsk-map %))
|
|
(if (:use-default-sente-router? options)
|
|
(sente/start-chsk-router! (:ch-recv sente-chsk-map) #(default-event-msg-handler sente-chsk-map %))))
|