penpot/frontend/src/app/util/websocket.cljs
2023-12-26 14:14:20 +01:00

119 lines
2.7 KiB
Clojure

;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns app.util.websocket
"A interface to webworkers exposed functionality."
(:require
[app.common.transit :as t]
[beicon.v2.core :as rx]
[goog.events :as ev])
(:import
goog.net.WebSocket
goog.net.WebSocket.EventType))
(defprotocol IWebSocket
(-stream [_] "Retrieve the message stream")
(-send [_ message] "send a message")
(-close [_] "close websocket")
(-open? [_] "check if the channel is open"))
(defn create
[uri]
(let [sb (rx/subject)
ws (WebSocket. #js {:autoReconnect true})
data (atom {})
lk1 (ev/listen ws EventType.MESSAGE
#(rx/push! sb {:type :message :payload (.-message %)}))
lk2 (ev/listen ws EventType.ERROR
#(rx/push! sb {:type :error :payload %}))
lk3 (ev/listen ws EventType.OPENED
#(rx/push! sb {:type :opened :payload %}))]
(.open ws (str uri))
(reify
IDeref
(-deref [_] (-deref data))
IReset
(-reset! [_ newval]
(-reset! data newval))
ISwap
(-swap! [_ f]
(-swap! data f))
(-swap! [_ f x]
(-swap! data f x))
(-swap! [_ f x y]
(-swap! data f x y))
(-swap! [_ f x y more]
(-swap! data f x y more))
IWatchable
(-notify-watches [_ oldval newval]
(-notify-watches data oldval newval))
(-add-watch [_ key f]
(-add-watch data key f))
(-remove-watch [_ key]
(-remove-watch data key))
IHash
(-hash [_] (goog/getUid ws))
IWebSocket
(-stream [_]
(->> sb
(rx/map (fn [{:keys [type payload] :as message}]
(cond-> message
(= :message type)
(assoc :payload (t/decode-str payload)))))))
(-send [_ msg]
(when (.isOpen ^js ws)
(.send ^js ws msg)))
(-open? [_]
(.isOpen ^js ws))
(-close [_]
(rx/end! sb)
(ev/unlistenByKey lk1)
(ev/unlistenByKey lk2)
(ev/unlistenByKey lk3)
(.close ^js ws)
(.dispose ^js ws)))))
(defn message-event?
^boolean
[msg]
(= (:type msg) :message))
(defn error-event?
^boolean
[msg]
(= (:type msg) :error))
(defn opened-event?
^boolean
[msg]
(= (:type msg) :opened))
(defn send!
[ws msg]
(-send ws (t/encode-str msg)))
(defn close!
[ws]
(-close ws))
(defn open?
[ws]
(-open? ws))
(defn get-rcv-stream
[ws]
(-stream ws))