diff --git a/frontend/src/app/main/data/workspace/notifications.cljs b/frontend/src/app/main/data/workspace/notifications.cljs index 1447cb113..e3578b0f3 100644 --- a/frontend/src/app/main/data/workspace/notifications.cljs +++ b/frontend/src/app/main/data/workspace/notifications.cljs @@ -19,6 +19,7 @@ [app.util.globals :refer [global]] [app.util.mouse :as mse] [app.util.object :as obj] + [app.util.rxops :as rxs] [app.util.time :as dt] [beicon.v2.core :as rx] [clojure.set :as set] @@ -82,7 +83,7 @@ ;; position changes. (->> stream (rx/filter mse/pointer-event?) - (rx/sample 50) + (rx/pipe (rxs/throttle 100)) (rx/map #(handle-pointer-send file-id (:pt %))))) (rx/take-until stoper))] diff --git a/frontend/src/app/util/rxops.cljs b/frontend/src/app/util/rxops.cljs new file mode 100644 index 000000000..f085d037e --- /dev/null +++ b/frontend/src/app/util/rxops.cljs @@ -0,0 +1,72 @@ +;; 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.rxops + (:require + [beicon.v2.core :as rx])) + +(defn- throttle-fn + [delay f] + (let [state + #js {:lastExecTime 0 + :timeoutId nil + :context nil + :args nil} + + execute-fn + (fn [] + (let [context (.-context ^js state) + args (.-args ^js state)] + (.apply f context args) + (set! (.-lastExecTime state) (js/Date.now)) + (set! (.-timeoutId state) nil))) + + wrapped-fn + (fn [] + (let [ctime (js/Date.now) + ltime (.-lastExecTime ^js state) + args (js-arguments)] + + (this-as this + (set! (.-context state) this) + (set! (.-args state) args)) + + (let [timeout-id (.-timeoutId state)] + (if (>= (- ctime ltime) delay) + (do + (when ^boolean timeout-id + (js/clearTimeout timeout-id) + (set! (.-timeoutId state) nil)) + (execute-fn)) + + (when-not ^boolean timeout-id + (set! (.-timeoutId state) + (js/setTimeout execute-fn (- delay ctime ltime))))))))] + + (specify! wrapped-fn + rx/IDisposable + (-dispose [_] + (js/clearTimeout (.-timeoutId state)) + (set! (.-lastExecTime state) 0) + (set! (.-timeoutId state) nil))))) + + +(defn throttle + "High performance rxjs throttle operation. It does not saturates the + macro-task queue of the js runtime on long burst of mouse + movements." + [delay] + (fn [source] + (rx/create + (fn [subs] + (let [next-fn (throttle-fn delay (partial rx/push! subs)) + error-fn (fn [cause] + (rx/dispose! next-fn) + (rx/error! subs cause)) + end-fn (fn [] + (rx/dispose! next-fn) + (rx/end! subs))] + (rx/sub! source next-fn error-fn end-fn))))))