mirror of https://github.com/logseq/logseq
fix: cache key bindings
parent
039c666062
commit
bd3479abda
|
@ -13,14 +13,21 @@
|
|||
[frontend.handler.config :as config-handler])
|
||||
(:import [goog.ui KeyboardShortcutHandler]))
|
||||
|
||||
(defn get-bindings
|
||||
[]
|
||||
(->> (vals @shortcut-config/config)
|
||||
;; function vals->bindings is too time-consuming. Here we cache the results.
|
||||
(defn- flatten-key-bindings
|
||||
[config]
|
||||
(->> config
|
||||
(into {})
|
||||
(map (fn [[k {:keys [binding]}]]
|
||||
{k binding}))
|
||||
(into {})))
|
||||
|
||||
(def m-flatten-key-bindings (util/memoize-last flatten-key-bindings))
|
||||
|
||||
(defn get-bindings
|
||||
[]
|
||||
(m-flatten-key-bindings (vals @shortcut-config/config)))
|
||||
|
||||
(defn- mod-key [shortcut]
|
||||
(str/replace shortcut #"(?i)mod"
|
||||
(if util/mac? "meta" "ctrl")))
|
||||
|
@ -48,11 +55,11 @@
|
|||
(defn normalize-user-keyname
|
||||
[k]
|
||||
(let [keynames {";" "semicolon"
|
||||
"=" "equals"
|
||||
"-" "dash"
|
||||
"[" "open-square-bracket"
|
||||
"]" "close-square-bracket"
|
||||
"'" "single-quote"}]
|
||||
"=" "equals"
|
||||
"-" "dash"
|
||||
"[" "open-square-bracket"
|
||||
"]" "close-square-bracket"
|
||||
"'" "single-quote"}]
|
||||
(some-> k
|
||||
(util/safe-lower-case)
|
||||
(str/replace #"[;=-\[\]']" (fn [s]
|
||||
|
|
|
@ -1432,3 +1432,21 @@
|
|||
(.then (fn [blob]
|
||||
(js/navigator.clipboard.write (clj->js [(js/ClipboardItem. (clj->js {(.-type blob) blob}))]))))
|
||||
(.catch js/console.error)))))))
|
||||
|
||||
|
||||
(defn memoize-last
|
||||
"Different from core.memoize, it only cache the last result.
|
||||
Returns a memoized version of a referentially transparent function. The
|
||||
memoized version of the function cache the the last result, and replay when calls
|
||||
with the same arguments, or update cache when with different arguments."
|
||||
[f]
|
||||
(let [last-mem (atom nil)
|
||||
last-args (atom nil)]
|
||||
(fn [& args]
|
||||
(if (or (nil? @last-mem)
|
||||
(not= @last-args args))
|
||||
(let [ret (apply f args)]
|
||||
(reset! last-args args)
|
||||
(reset! last-mem ret)
|
||||
ret)
|
||||
@last-mem))))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns frontend.util-test
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
[frontend.util :as util]))
|
||||
[frontend.util :as util]
|
||||
[frontend.modules.shortcut.data-helper :as shortcut-data-helper]))
|
||||
|
||||
(deftest test-find-first
|
||||
(testing "find-first"
|
||||
|
@ -31,3 +32,78 @@
|
|||
(is (= (util/node-path.join "content://a/b" "../d.md") "content://a/d.md"))
|
||||
(is (= (util/node-path.join "https://logseq.com/a/b" "c/d.md") "https://logseq.com/a/b/c/d.md"))))
|
||||
|
||||
(deftest test-memoize-last
|
||||
(testing "memoize-last add test"
|
||||
(let [actual-ops (atom 0)
|
||||
m+ (util/memoize-last (fn [x1 x2]
|
||||
(swap! actual-ops inc) ;; side effect for counting
|
||||
(+ x1 x2)))]
|
||||
(is (= (m+ 1 1) 2))
|
||||
(is (= @actual-ops 1))
|
||||
(is (= (m+ 1 1) 2))
|
||||
(is (= (m+ 1 1) 2))
|
||||
(is (= @actual-ops 1))
|
||||
(is (= (m+ 1 2) 3))
|
||||
(is (= @actual-ops 2))
|
||||
(is (= (m+ 2 3) 5))
|
||||
(is (= @actual-ops 3))
|
||||
(is (= (m+ 3 5) 8))
|
||||
(is (= @actual-ops 4))
|
||||
(is (= (m+ 3 5) 8))
|
||||
(is (= @actual-ops 4))))
|
||||
|
||||
(testing "memoize-last nested mapping test"
|
||||
(let [actual-ops (atom 0)
|
||||
flatten-f (util/memoize-last (fn [& args]
|
||||
(swap! actual-ops inc) ;; side effect for counting
|
||||
(apply #'shortcut-data-helper/flatten-key-bindings args)))
|
||||
target (atom {:part1 {:date-picker/complete {:binding "enter"
|
||||
:fn "ui-handler/shortcut-complete"}
|
||||
:date-picker/prev-day {:binding "left"
|
||||
:fn "ui-handler/shortcut-prev-day"}}
|
||||
:part2 {:date-picker/next-day {:binding "right"
|
||||
:fn "ui-handler/shortcut-next-day"}
|
||||
:date-picker/prev-week {:binding ["up" "ctrl+p"]
|
||||
:fn "ui-handler/shortcut-prev-week"}}})]
|
||||
(is (= (flatten-f (vals @target)) {:date-picker/complete "enter"
|
||||
:date-picker/prev-day "left"
|
||||
:date-picker/next-day "right"
|
||||
:date-picker/prev-week ["up" "ctrl+p"]}))
|
||||
(is (= @actual-ops 1))
|
||||
(is (= (flatten-f (vals @target)) {:date-picker/complete "enter"
|
||||
:date-picker/prev-day "left"
|
||||
:date-picker/next-day "right"
|
||||
:date-picker/prev-week ["up" "ctrl+p"]}))
|
||||
(is (= @actual-ops 1))
|
||||
;; edit value
|
||||
(swap! target assoc-in [:part1 :date-picker/complete :binding] "tab")
|
||||
(is (= (flatten-f (vals @target)) {:date-picker/complete "tab"
|
||||
:date-picker/prev-day "left"
|
||||
:date-picker/next-day "right"
|
||||
:date-picker/prev-week ["up" "ctrl+p"]}))
|
||||
(is (= @actual-ops 2))
|
||||
(is (= (flatten-f (vals @target)) {:date-picker/complete "tab"
|
||||
:date-picker/prev-day "left"
|
||||
:date-picker/next-day "right"
|
||||
:date-picker/prev-week ["up" "ctrl+p"]}))
|
||||
(is (= @actual-ops 2))
|
||||
(is (= (flatten-f (vals @target)) {:date-picker/complete "tab"
|
||||
:date-picker/prev-day "left"
|
||||
:date-picker/next-day "right"
|
||||
:date-picker/prev-week ["up" "ctrl+p"]}))
|
||||
(is (= @actual-ops 2))
|
||||
;; edit key
|
||||
(swap! target assoc :part3 {:date-picker/next-week {:binding "down"
|
||||
:fn "ui-handler/shortcut-next-week"}})
|
||||
(is (= (flatten-f (vals @target)) {:date-picker/complete "tab"
|
||||
:date-picker/prev-day "left"
|
||||
:date-picker/next-day "right"
|
||||
:date-picker/prev-week ["up" "ctrl+p"]
|
||||
:date-picker/next-week "down"}))
|
||||
(is (= @actual-ops 3))
|
||||
(is (= (flatten-f (vals @target)) {:date-picker/complete "tab"
|
||||
:date-picker/prev-day "left"
|
||||
:date-picker/next-day "right"
|
||||
:date-picker/prev-week ["up" "ctrl+p"]
|
||||
:date-picker/next-week "down"}))
|
||||
(is (= @actual-ops 3)))))
|
||||
|
|
Loading…
Reference in New Issue