perf: debounce search

This commit is contained in:
Tienson Qin
2024-09-21 08:20:21 +08:00
parent 2738f2cba5
commit c392a9c321
4 changed files with 121 additions and 103 deletions

View File

@@ -106,7 +106,9 @@
(take 5 items))))
node-exists? (let [blocks-result (keep :source-block (get-in results [:nodes :items]))]
(when-not (string/blank? input)
(or (db/get-page (string/trim (last (string/split input "/"))))
(or (some-> (last (string/split input "/"))
string/trim
db/get-page)
(some (fn [block]
(and
(:block/tags block)
@@ -223,7 +225,7 @@
new-result)))]))
(defn- page-item
[repo page q]
[repo page]
(let [entity (db/entity [:block/uuid (:block/uuid page)])
source-page (model/get-alias-source-page repo (:db/id entity))
icon (cond
@@ -235,7 +237,7 @@
"whiteboard"
:else
"page")
title (highlight-content-query (title/block-unique-title page) q)
title (title/block-unique-title page)
title' (if source-page (str title " -> alias: " (:block/title source-page)) title)]
(hash-map :icon icon
:icon-theme :gray
@@ -267,9 +269,11 @@
(swap! !results assoc-in [:current-page :status] :loading)
(p/let [blocks (search/block-search repo @!input opts)
blocks (remove nil? blocks)
blocks (search/fuzzy-search blocks @!input {:limit 100
:extract-fn :block/title})
items (keep (fn [block]
(if (:page? block)
(page-item repo block !input)
(page-item repo block)
(block-item repo block current-page !input))) blocks)]
(if (= group :current-page)
(let [items-on-current-page (filter :current-page? items)]
@@ -656,8 +660,7 @@
e-type (gobj/getValueByKeys e "type")
composing-end? (= e-type "compositionend")
!input (::input state)
input-ref @(::input-ref state)
!load-results-throttled (::load-results-throttled state)]
input-ref @(::input-ref state)]
;; update the input value in the UI
(reset! !input input)
@@ -665,14 +668,9 @@
(reset! (::input-changed? state) true)
;; ensure that there is a throttled version of the load-results function
(when-not @!load-results-throttled
(reset! !load-results-throttled (gfun/throttle load-results 50)))
;; retrieve the load-results function and update all the results
(when (or (not composing?) composing-end?)
(when-let [load-results-throttled @!load-results-throttled]
(load-results-throttled :default state))))))
(load-results :default state)))))
(defn- open-current-item-link
"Opens a link for the current item if a page or block. For pages, opens the
@@ -777,14 +775,23 @@
[state all-items opts]
(let [highlighted-item @(::highlighted-item state)
input @(::input state)
input-ref (::input-ref state)]
input-ref (::input-ref state)
debounced-on-change (rum/use-callback
(gfun/debounce
(fn [e]
(let [new-value (.-value (.-target e))]
(handle-input-change state e)
(when-let [on-change (:on-input-change opts)]
(on-change new-value))))
150)
[])]
;; use-effect [results-ordered input] to check whether the highlighted item is still in the results,
;; if not then clear that puppy out!
;; This was moved to a functional component
(rum/use-effect! (fn []
(when (and highlighted-item (= -1 (.indexOf all-items (dissoc highlighted-item :mouse-enter-triggered-highlight))))
(reset! (::highlighted-item state) nil)))
[all-items])
[all-items])
(rum/use-effect! (fn [] (load-results :default state)) [])
[:div {:class "bg-gray-02 border-b border-1 border-gray-07"}
[:input.cp__cmdk-search-input
@@ -793,30 +800,29 @@
:autoComplete "off"
:placeholder (input-placeholder false)
:ref #(when-not @input-ref (reset! input-ref %))
:on-change (fn [e]
(let [new-value (.-value (.-target e))]
(handle-input-change state e)
(when-let [on-change (:on-input-change opts)]
(on-change new-value))))
:on-change debounced-on-change
:on-blur (fn [_e]
(when-let [on-blur (:on-input-blur opts)]
(on-blur input)))
:on-composition-end (fn [e] (handle-input-change state e))
:on-key-down (fn [e]
(p/let [value (.-value @input-ref)
last-char (last value)
backspace? (= (util/ekey e) "Backspace")
filter-group (:group @(::filter state))
slash? (= (util/ekey e) "/")
namespace-pages (when (and slash? (contains? #{:whiteboards} filter-group))
(search/block-search (state/get-current-repo) (str value "/") {}))
namespace-page-matched? (some #(string/includes? % "/") namespace-pages)]
(when (and filter-group
(or (and slash? (not namespace-page-matched?))
(and backspace? (= last-char "/"))
(and backspace? (= input ""))))
(reset! (::filter state) nil)
(load-results :default state))))
:on-composition-end (gfun/debounce (fn [e] (handle-input-change state e)) 150)
:on-key-down (gfun/debounce
(fn [e]
(p/let [value (.-value @input-ref)
last-char (last value)
backspace? (= (util/ekey e) "Backspace")
filter-group (:group @(::filter state))
slash? (= (util/ekey e) "/")
namespace-pages (when (and slash? (contains? #{:whiteboards} filter-group))
(search/block-search (state/get-current-repo) (str value "/") {}))
namespace-page-matched? (some #(string/includes? % "/") namespace-pages)]
(when (and filter-group
(or (and slash? (not namespace-page-matched?))
(and backspace? (= last-char "/"))
(and backspace? (= input ""))))
(reset! (::filter state) nil)
;; (load-results :default state)
)))
150)
:default-value input}]]))
(defn rand-tip
@@ -921,49 +927,48 @@
(rum/defcs cmdk
< rum/static
rum/reactive
{:will-mount
(fn [state]
(when-not (:sidebar? (last (:rum/args state)))
(shortcut/unlisten-all!))
state)
rum/reactive
{:will-mount
(fn [state]
(when-not (:sidebar? (last (:rum/args state)))
(shortcut/unlisten-all!))
state)
:will-unmount
(fn [state]
(when-not (:sidebar? (last (:rum/args state)))
(shortcut/listen-all!))
state)}
{:init (fn [state]
(let [search-mode (:search/mode @state/state)
opts (last (:rum/args state))]
(assoc state
::ref (atom nil)
::filter (if (and search-mode
(not (contains? #{:global :graph} search-mode))
(not (:sidebar? opts)))
(atom {:group search-mode})
(atom nil))
::input (atom (or (:initial-input opts) "")))))
:will-unmount (fn [state]
(state/set-state! :search/mode nil)
state)}
(mixins/event-mixin
(fn [state]
(let [ref @(::ref state)]
(mixins/on-key-down state {}
{:target ref
:all-handler (fn [e _key] (keydown-handler state e))})
(mixins/on-key-up state {} (fn [e _key]
(keyup-handler state e))))))
(rum/local false ::shift?)
(rum/local false ::meta?)
(rum/local nil ::highlighted-group)
(rum/local nil ::highlighted-item)
(rum/local default-results ::results)
(rum/local nil ::load-results-throttled)
(rum/local nil ::scroll-container-ref)
(rum/local nil ::input-ref)
(rum/local false ::input-changed?)
:will-unmount
(fn [state]
(when-not (:sidebar? (last (:rum/args state)))
(shortcut/listen-all!))
state)}
{:init (fn [state]
(let [search-mode (:search/mode @state/state)
opts (last (:rum/args state))]
(assoc state
::ref (atom nil)
::filter (if (and search-mode
(not (contains? #{:global :graph} search-mode))
(not (:sidebar? opts)))
(atom {:group search-mode})
(atom nil))
::input (atom (or (:initial-input opts) "")))))
:will-unmount (fn [state]
(state/set-state! :search/mode nil)
state)}
(mixins/event-mixin
(fn [state]
(let [ref @(::ref state)]
(mixins/on-key-down state {}
{:target ref
:all-handler (fn [e _key] (keydown-handler state e))})
(mixins/on-key-up state {} (fn [e _key]
(keyup-handler state e))))))
(rum/local false ::shift?)
(rum/local false ::meta?)
(rum/local nil ::highlighted-group)
(rum/local nil ::highlighted-item)
(rum/local default-results ::results)
(rum/local nil ::scroll-container-ref)
(rum/local nil ::input-ref)
(rum/local false ::input-changed?)
[state {:keys [sidebar?] :as opts}]
(let [*input (::input state)
search-mode (:search/mode @state/state)
@@ -987,22 +992,23 @@
(search-only state (string/capitalize (name group-filter)))])
(let [items (filter
(fn [[_group-name group-key group-count _group-items]]
(and (not= 0 group-count)
(if-not group-filter true
(or (= group-filter group-key)
(and (= group-filter :nodes)
(= group-key :current-page))
(and (contains? #{:create} group-filter)
(= group-key :create))))))
results-ordered)]
(if (seq items)
(fn [[_group-name group-key group-count _group-items]]
(and (not= 0 group-count)
(if-not group-filter true
(or (= group-filter group-key)
(and (= group-filter :nodes)
(= group-key :current-page))
(and (contains? #{:create} group-filter)
(= group-key :create))))))
results-ordered)]
(when-not (= ["Filters"] (map first items))
(if (seq items)
(for [[group-name group-key _group-count group-items] items]
(let [title (string/capitalize group-name)]
(result-group state title group-key group-items first-item sidebar?)))
[:div.flex.flex-col.p-4.opacity-50
(when-not (string/blank? @*input)
"No matched results")]))]
"No matched results")])))]
(when-not sidebar? (hints state))]))
(rum/defc cmdk-modal [props]