mirror of
https://github.com/penpot/penpot.git
synced 2025-02-09 00:28:20 -05:00
🐛 Fix unexpected rx scheduler saturation on mouse movement burst
Fixed with custom trailing-edge throttling mechanism
This commit is contained in:
parent
ccf063b8ef
commit
88c7ac379b
2 changed files with 74 additions and 1 deletions
|
@ -19,6 +19,7 @@
|
||||||
[app.util.globals :refer [global]]
|
[app.util.globals :refer [global]]
|
||||||
[app.util.mouse :as mse]
|
[app.util.mouse :as mse]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
|
[app.util.rxops :as rxs]
|
||||||
[app.util.time :as dt]
|
[app.util.time :as dt]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[clojure.set :as set]
|
[clojure.set :as set]
|
||||||
|
@ -82,7 +83,7 @@
|
||||||
;; position changes.
|
;; position changes.
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/filter mse/pointer-event?)
|
(rx/filter mse/pointer-event?)
|
||||||
(rx/sample 50)
|
(rx/pipe (rxs/throttle 100))
|
||||||
(rx/map #(handle-pointer-send file-id (:pt %)))))
|
(rx/map #(handle-pointer-send file-id (:pt %)))))
|
||||||
|
|
||||||
(rx/take-until stoper))]
|
(rx/take-until stoper))]
|
||||||
|
|
72
frontend/src/app/util/rxops.cljs
Normal file
72
frontend/src/app/util/rxops.cljs
Normal file
|
@ -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))))))
|
Loading…
Add table
Reference in a new issue