From 560fceb7716baeba64a5e0d3a68ba12f00d3b6e9 Mon Sep 17 00:00:00 2001 From: Isaac Johnston Date: Wed, 23 Jun 2021 23:53:02 +1200 Subject: [PATCH] Fix performance of auto-scrolling epoch navigation with debounce --- CHANGELOG.md | 4 +++ src/day8/re_frame_10x/fx/debounce.cljs | 26 +++++++++++++++++++ src/day8/re_frame_10x/fx/scroll.cljs | 9 +++++++ .../navigation/epochs/events.cljs | 16 ++++++++++++ .../re_frame_10x/navigation/epochs/views.cljs | 4 +-- 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/day8/re_frame_10x/fx/debounce.cljs create mode 100644 src/day8/re_frame_10x/fx/scroll.cljs diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d2ca7c0..9d36b931 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). +#### Fixed + +- Fix performance of auto-scrolling epoch navigation by using debounce. + #### Changed - Upgrade re-highlight to 1.0.0. Includes [highlight.js 11.0.1](https://github.com/highlightjs/highlight.js/blob/main/CHANGES.md#version-1100). diff --git a/src/day8/re_frame_10x/fx/debounce.cljs b/src/day8/re_frame_10x/fx/debounce.cljs new file mode 100644 index 00000000..6e02ab09 --- /dev/null +++ b/src/day8/re_frame_10x/fx/debounce.cljs @@ -0,0 +1,26 @@ +(ns day8.re-frame-10x.fx.debounce + (:require + [day8.re-frame-10x.inlined-deps.re-frame.v1v1v2.re-frame.core :as rf])) + +(defn now [] (.getTime (js/Date.))) + +(def registered-keys (atom nil)) + +(defn dispatch-if-not-superceded [{:keys [key delay event time-received]}] + (when (= time-received (get @registered-keys key)) + ;; no new events on this key! + (rf/dispatch event))) + +(defn dispatch-later [{:keys [delay] :as debounce}] + (js/setTimeout + (fn [] (dispatch-if-not-superceded debounce)) + delay)) + +(rf/reg-fx + ::dispatch + (fn dispatch-debounce [{:keys [key event delay] :as debounce}] + (when (not (and (keyword? key) (vector? event) (integer? delay))) + (rf/console :error "re-frame-10x ::debounce/dispatch invalid argument")) + (let [ts (now)] + (swap! registered-keys assoc (:key debounce) ts) + (dispatch-later (assoc debounce :time-received ts))))) \ No newline at end of file diff --git a/src/day8/re_frame_10x/fx/scroll.cljs b/src/day8/re_frame_10x/fx/scroll.cljs new file mode 100644 index 00000000..ae8d2e35 --- /dev/null +++ b/src/day8/re_frame_10x/fx/scroll.cljs @@ -0,0 +1,9 @@ +(ns day8.re-frame-10x.fx.scroll + (:require + [day8.re-frame-10x.inlined-deps.re-frame.v1v1v2.re-frame.core :as rf])) + +(rf/reg-fx + ::into-view + (fn [{:keys [js-dom]}] + (when (instance? js/Element js-dom) + (.scrollIntoView js-dom)))) \ No newline at end of file diff --git a/src/day8/re_frame_10x/navigation/epochs/events.cljs b/src/day8/re_frame_10x/navigation/epochs/events.cljs index f4e884a9..8900b1db 100644 --- a/src/day8/re_frame_10x/navigation/epochs/events.cljs +++ b/src/day8/re_frame_10x/navigation/epochs/events.cljs @@ -5,6 +5,8 @@ [re-frame.db] [re-frame.trace] [day8.re-frame-10x.inlined-deps.re-frame.v1v1v2.re-frame.core :as rf] + [day8.re-frame-10x.fx.debounce :as debounce] + [day8.re-frame-10x.fx.scroll :as scroll] [day8.re-frame-10x.tools.metamorphic :as metam] [day8.re-frame-10x.tools.coll :as tools.coll])) @@ -12,6 +14,20 @@ [m] (-> m :match-info first :id)) +(rf/reg-event-fx + ::scroll-into-view-debounced + [rf/trim-v] + (fn [_ [js-dom]] + {:fx [[::debounce/dispatch {:key ::scroll-into-view + :event [::scroll-into-view js-dom] + :delay 128}]]})) + +(rf/reg-event-fx + ::scroll-into-view + [rf/trim-v] + (fn [_ [js-dom]] + {:fx [[::scroll/into-view {:js-dom js-dom}]]})) + (rf/reg-event-fx ::receive-new-traces [rf/trim-v] diff --git a/src/day8/re_frame_10x/navigation/epochs/views.cljs b/src/day8/re_frame_10x/navigation/epochs/views.cljs index d3649704..5281f9f8 100644 --- a/src/day8/re_frame_10x/navigation/epochs/views.cljs +++ b/src/day8/re_frame_10x/navigation/epochs/views.cljs @@ -41,12 +41,12 @@ {:component-did-mount (fn [this] (when @active? - (.scrollIntoView (rdom/dom-node this)))) + (rf/dispatch [::epochs.events/scroll-into-view-debounced (rdom/dom-node this)]))) :component-did-update (fn [this] (when @active? - (.scrollIntoView (rdom/dom-node this)))) + (rf/dispatch [::epochs.events/scroll-into-view-debounced (rdom/dom-node this)]))) :reagent-render (fn [event id]