Procházet zdrojové kódy

Merge pull request #11674 from logseq/refactor/custom-react-hooks

Refactor: custom react hooks
rcmerci před 11 měsíci
rodič
revize
6518fd948e

+ 1 - 0
.clj-kondo/config.edn

@@ -122,6 +122,7 @@
              frontend.handler.route route-handler
              frontend.handler.search search-handler
              frontend.handler.ui ui-handler
+             frontend.hooks hooks
              frontend.idb idb
              frontend.loader loader
              frontend.mixins mixins

+ 48 - 47
src/main/frontend/components/block.cljs

@@ -55,6 +55,7 @@
             [frontend.handler.route :as route-handler]
             [frontend.handler.ui :as ui-handler]
             [frontend.handler.whiteboard :as whiteboard-handler]
+            [frontend.hooks :as hooks]
             [frontend.mixins :as mixins]
             [frontend.mobile.intent :as mobile-intent]
             [frontend.mobile.util :as mobile-util]
@@ -273,13 +274,13 @@
   (let [handle-props {}
         add-resizing-class! #(dom/add-class! js/document.documentElement "is-resizing-buf")
         remove-resizing-class! #(dom/remove-class! js/document.documentElement "is-resizing-buf")
-        *handle-left (rum/use-ref nil)
-        *handle-right (rum/use-ref nil)]
+        *handle-left (hooks/use-ref nil)
+        *handle-right (hooks/use-ref nil)]
 
     (rum/use-effect!
      (fn []
-       (doseq [el [(rum/deref *handle-left)
-                   (rum/deref *handle-right)]]
+       (doseq [el [(hooks/deref *handle-left)
+                   (hooks/deref *handle-right)]]
          (-> (js/interact el)
              (.draggable
               (bean/->js
@@ -767,12 +768,12 @@
 
 (rum/defc popup-preview-impl
   [children {:keys [*timer *timer1 visible? set-visible! render *el-popup]}]
-  (let [*el-trigger (rum/use-ref nil)]
+  (let [*el-trigger (hooks/use-ref nil)]
     (rum/use-effect!
      (fn []
        (when (true? visible?)
          (shui/popup-show!
-          (rum/deref *el-trigger) render
+          (hooks/deref *el-trigger) render
           {:root-props {:onOpenChange (fn [v] (set-visible! v))
                         :modal false}
            :content-props {:class "ls-preview-popup"
@@ -780,15 +781,15 @@
                            :onEscapeKeyDown (fn [^js e]
                                               (when (state/editing?)
                                                 (.preventDefault e)
-                                                (some-> (rum/deref *el-popup) (.focus))))}
+                                                (some-> (hooks/deref *el-popup) (.focus))))}
            :as-dropdown? false}))
 
        (when (false? visible?)
          (shui/popup-hide!)
          (when (state/get-edit-block)
            (state/clear-edit!)))
-       (rum/set-ref! *timer nil)
-       (rum/set-ref! *timer1 nil)
+       (hooks/set-ref! *timer nil)
+       (hooks/set-ref! *timer1 nil)
         ;; teardown
        (fn []
          (when visible?
@@ -799,33 +800,33 @@
      {:ref *el-trigger
       :on-mouse-enter (fn [^js e]
                         (when (= (some-> (.-target e) (.closest ".preview-ref-link"))
-                                 (rum/deref *el-trigger))
-                          (let [timer (rum/deref *timer)
-                                timer1 (rum/deref *timer1)]
+                                 (hooks/deref *el-trigger))
+                          (let [timer (hooks/deref *timer)
+                                timer1 (hooks/deref *timer1)]
                             (when-not timer
-                              (rum/set-ref! *timer
-                                            (js/setTimeout #(set-visible! true) 1000)))
+                              (hooks/set-ref! *timer
+                                              (js/setTimeout #(set-visible! true) 1000)))
                             (when timer1
                               (js/clearTimeout timer1)
-                              (rum/set-ref! *timer1 nil)))))
+                              (hooks/set-ref! *timer1 nil)))))
       :on-mouse-leave (fn []
-                        (let [timer (rum/deref *timer)
-                              timer1 (rum/deref *timer1)]
+                        (let [timer (hooks/deref *timer)
+                              timer1 (hooks/deref *timer1)]
                           (when (or (number? timer) (number? timer1))
                             (when timer
                               (js/clearTimeout timer)
-                              (rum/set-ref! *timer nil))
+                              (hooks/set-ref! *timer nil))
                             (when-not timer1
-                              (rum/set-ref! *timer1
-                                            (js/setTimeout #(set-visible! false) 300))))))}
+                              (hooks/set-ref! *timer1
+                                              (js/setTimeout #(set-visible! false) 300))))))}
      children]))
 
 (rum/defc page-preview-trigger
   [{:keys [children sidebar? open? manual?] :as config} page-entity]
-  (let [*timer (rum/use-ref nil)                            ;; show
-        *timer1 (rum/use-ref nil)                           ;; hide
-        *el-popup (rum/use-ref nil)
-        *el-wrap (rum/use-ref nil)
+  (let [*timer (hooks/use-ref nil)                            ;; show
+        *timer1 (hooks/use-ref nil)                           ;; hide
+        *el-popup (hooks/use-ref nil)
+        *el-wrap (hooks/use-ref nil)
         [in-popup? set-in-popup!] (rum/use-state nil)
         [visible? set-visible!] (rum/use-state nil)
         ;; set-visible! (fn debug-visible [v] (js/console.warn "debug: visible" v) (set-visible! v))
@@ -834,7 +835,7 @@
 
                                    (rum/use-effect!
                                     (fn []
-                                      (let [el-popup (rum/deref *el-popup)
+                                      (let [el-popup (hooks/deref *el-popup)
                                             focus! #(js/setTimeout (fn [] (.focus el-popup)))]
                                         (set-ready! true)
                                         (focus!)
@@ -851,23 +852,23 @@
                                                :font-weight 500
                                                :padding-bottom 64}
                                        :on-mouse-enter (fn []
-                                                         (when-let [timer1 (rum/deref *timer1)]
+                                                         (when-let [timer1 (hooks/deref *timer1)]
                                                            (js/clearTimeout timer1)))
                                        :on-mouse-leave (fn []
                                                          ;; check the top popup whether is the preview popup
                                                          (when (ui/last-shui-preview-popup?)
-                                                           (rum/set-ref! *timer1
-                                                                         (js/setTimeout #(set-visible! false) 500))))}
+                                                           (hooks/set-ref! *timer1
+                                                                           (js/setTimeout #(set-visible! false) 500))))}
                                       (when-let [page-cp (and ready? (state/get-page-blocks-cp))]
                                         (page-cp {:repo (state/get-current-repo)
                                                   :page-name (str (:block/uuid source))
                                                   :sidebar? sidebar?
-                                                  :scroll-container (some-> (rum/deref *el-popup) (.closest ".ls-preview-popup"))
+                                                  :scroll-container (some-> (hooks/deref *el-popup) (.closest ".ls-preview-popup"))
                                                   :preview? true}))])))]
 
     (rum/use-effect!
      (fn []
-       (if (some-> (rum/deref *el-wrap) (.closest "[data-radix-popper-content-wrapper]"))
+       (if (some-> (hooks/deref *el-wrap) (.closest "[data-radix-popper-content-wrapper]"))
          (set-in-popup! true)
          (set-in-popup! false)))
      [])
@@ -1193,8 +1194,8 @@
 
 (rum/defc block-reference-preview
   [children {:keys [repo config id]}]
-  (let [*timer (rum/use-ref nil)                            ;; show
-        *timer1 (rum/use-ref nil)                           ;; hide
+  (let [*timer (hooks/use-ref nil)                            ;; show
+        *timer1 (hooks/use-ref nil)                           ;; hide
         [visible? set-visible!] (rum/use-state nil)
         _ #_:clj-kondo/ignore (rum/defc render []
                                 [:div.tippy-wrapper.as-block
@@ -1202,13 +1203,13 @@
                                           :font-weight 500
                                           :text-align "left"}
                                   :on-mouse-enter (fn []
-                                                    (when-let [timer1 (rum/deref *timer1)]
+                                                    (when-let [timer1 (hooks/deref *timer1)]
                                                       (js/clearTimeout timer1)))
 
                                   :on-mouse-leave (fn []
                                                     (when (ui/last-shui-preview-popup?)
-                                                      (rum/set-ref! *timer1
-                                                                    (js/setTimeout #(set-visible! false) 500))))}
+                                                      (hooks/set-ref! *timer1
+                                                                      (js/setTimeout #(set-visible! false) 500))))}
                                  [(breadcrumb config repo id {:indent? true})
                                   (blocks-container
                                    (assoc config :id (str id) :preview? true)
@@ -2750,11 +2751,11 @@
     (let [[result set-result!] (rum/use-state nil)
           repo (state/get-current-repo)
           [status-history time-spent] result]
-      (rum/use-effect!
+      (hooks/use-effect!
        (fn []
          (p/let [result (db-async/<task-spent-time repo (:db/id block))]
            (set-result! result)))
-       [(:db/id (:logseq.task/status block))])
+       [(:logseq.task/status block)])
       (when (and time-spent (> time-spent 0))
         [:div.text-sm.time-spent.ml-1
          (shui/button
@@ -3820,8 +3821,8 @@
   [config options]
   (let [block (or (:code-block config) (:block config))
         container-id (:container-id config)
-        *mode-ref (rum/use-ref nil)
-        *actions-ref (rum/use-ref nil)]
+        *mode-ref (hooks/use-ref nil)
+        *actions-ref (hooks/use-ref nil)]
 
     (when options
       (let [html-export? (:html-export? config)
@@ -3839,10 +3840,10 @@
             [:div.ui-fenced-code-editor.flex.w-full
              {:ref (fn [el]
                      (set-inside-portal? (and el (whiteboard-handler/inside-portal? el))))
-              :on-mouse-over #(dom/add-class! (rum/deref *actions-ref) "opacity-100")
+              :on-mouse-over #(dom/add-class! (hooks/deref *actions-ref) "opacity-100")
               :on-mouse-leave (fn [e]
                                 (when (dom/has-class? (.-target e) "code-editor")
-                                  (dom/remove-class! (rum/deref *actions-ref) "opacity-100")))}
+                                  (dom/remove-class! (hooks/deref *actions-ref) "opacity-100")))}
              (cond
                (nil? inside-portal?) nil
 
@@ -4123,7 +4124,7 @@
                                     {:top? top?
                                      :bottom? bottom?})))
         virtualized? (and virtualized? (seq blocks))
-        *virtualized-ref (rum/use-ref nil)
+        *virtualized-ref (hooks/use-ref nil)
         virtual-opts (when virtualized?
                        {:ref *virtualized-ref
                         :custom-scroll-parent (or (:scroll-container config)
@@ -4143,7 +4144,7 @@
                                                       block
                                                       {:top? top?
                                                        :bottom? bottom?})))})
-        *wrap-ref (rum/use-ref nil)]
+        *wrap-ref (hooks/use-ref nil)]
     (rum/use-effect!
      (fn []
        (when virtualized?
@@ -4156,13 +4157,13 @@
          (let [^js *ob (volatile! nil)]
            (js/setTimeout
             (fn []
-              (when-let [_inst (rum/deref *virtualized-ref)]
-                (when-let [^js target (.-firstElementChild (rum/deref *wrap-ref))]
-                  (let [set-wrap-h! #(when-let [ref (rum/deref *wrap-ref)] (set! (.-height (.-style ref)) %))
+              (when-let [_inst (hooks/deref *virtualized-ref)]
+                (when-let [^js target (.-firstElementChild (hooks/deref *wrap-ref))]
+                  (let [set-wrap-h! #(when-let [ref (hooks/deref *wrap-ref)] (set! (.-height (.-style ref)) %))
                         set-wrap-h! (debounce set-wrap-h! 16)
                         ob (js/ResizeObserver.
                             (fn []
-                              (when-let [h (and (rum/deref *wrap-ref)
+                              (when-let [h (and (hooks/deref *wrap-ref)
                                                 (.-height (.-style target)))]
                                    ;(prn "==>> debug: " h)
                                 (set-wrap-h! h))))]

+ 3 - 2
src/main/frontend/components/cmdk/core.cljs

@@ -10,6 +10,7 @@
             [frontend.db.async :as db-async]
             [frontend.db.model :as model]
             [frontend.extensions.pdf.utils :as pdf-utils]
+            [frontend.handler.block :as block-handler]
             [frontend.handler.command-palette :as cp-handler]
             [frontend.handler.db-based.page :as db-page-handler]
             [frontend.handler.editor :as editor-handler]
@@ -17,7 +18,7 @@
             [frontend.handler.page :as page-handler]
             [frontend.handler.route :as route-handler]
             [frontend.handler.whiteboard :as whiteboard-handler]
-            [frontend.handler.block :as block-handler]
+            [frontend.hooks :as hooks]
             [frontend.mixins :as mixins]
             [frontend.modules.shortcut.core :as shortcut]
             [frontend.modules.shortcut.utils :as shortcut-utils]
@@ -778,7 +779,7 @@
   (let [highlighted-item @(::highlighted-item state)
         input @(::input state)
         input-ref (::input-ref state)
-        debounced-on-change (rum/use-callback
+        debounced-on-change (hooks/use-callback
                              (gfun/debounce
                               (fn [e]
                                 (let [new-value (.-value (.-target e))]

+ 30 - 29
src/main/frontend/components/cmdk/list_item.cljs

@@ -1,10 +1,11 @@
 (ns frontend.components.cmdk.list-item
   (:require
    ["remove-accents" :as remove-accents]
-   [rum.core :as rum]
    [clojure.string :as string]
+   [frontend.hooks :as hooks]
    [goog.string :as gstring]
-   [logseq.shui.ui :as shui]))
+   [logseq.shui.ui :as shui]
+   [rum.core :as rum]))
 
 (defn- to-string [input]
   (cond
@@ -40,11 +41,11 @@
             segs (string/split highlighted-text #"<:hlmarker>")]
         (if (seq segs)
           (into [:span]
-            (map-indexed (fn [i seg]
-                           (if (even? i)
-                             [:span seg]
-                             [:span {:class "ui__list-item-highlighted-span"} seg]))
-              segs))
+                (map-indexed (fn [i seg]
+                               (if (even? i)
+                                 [:span seg]
+                                 [:span {:class "ui__list-item-highlighted-span"} seg]))
+                             segs))
           [:span normal-text])))))
 
 (rum/defc root [{:keys [group icon icon-theme query text info shortcut value-label value
@@ -52,29 +53,29 @@
                         hoverable compact rounded on-mouse-enter component-opts source-page] :as _props
                  :or {hoverable true rounded true}}
                 {:keys [app-config]}]
-  (let [ref (rum/create-ref)
+  (let [ref (hooks/create-ref)
         highlight-query (partial highlight-query* app-config query)
         [hover? set-hover?] (rum/use-state false)]
     (rum/use-effect!
-      (fn []
-        (when (and highlighted on-highlight)
-          (on-highlight ref)))
-      [highlighted on-highlight-dep])
+     (fn []
+       (when (and highlighted on-highlight)
+         (on-highlight ref)))
+     [highlighted on-highlight-dep])
     [:div (merge
-            {:style {:opacity (if highlighted 1 0.8)}
-             :class (cond-> "flex flex-col transition-opacity"
-                      highlighted (str " !opacity-100 bg-gray-03-alpha dark:bg-gray-04-alpha")
-                      hoverable (str " transition-all duration-50 ease-in !opacity-75 hover:!opacity-100 hover:cursor-pointer hover:bg-gradient-to-r hover:from-gray-03-alpha hover:to-gray-01-alpha from-0% to-100%")
-                      (and hoverable rounded) (str " !rounded-lg")
-                      (not compact) (str " py-4 px-6 gap-1")
-                      compact (str " py-1.5 px-3 gap-0.5")
-                      (not highlighted) (str " "))
-             :ref ref
-             :on-click (when on-click on-click)
-             :on-mouse-over #(set-hover? true)
-             :on-mouse-out #(set-hover? false)
-             :on-mouse-enter (when on-mouse-enter on-mouse-enter)}
-            component-opts)
+           {:style {:opacity (if highlighted 1 0.8)}
+            :class (cond-> "flex flex-col transition-opacity"
+                     highlighted (str " !opacity-100 bg-gray-03-alpha dark:bg-gray-04-alpha")
+                     hoverable (str " transition-all duration-50 ease-in !opacity-75 hover:!opacity-100 hover:cursor-pointer hover:bg-gradient-to-r hover:from-gray-03-alpha hover:to-gray-01-alpha from-0% to-100%")
+                     (and hoverable rounded) (str " !rounded-lg")
+                     (not compact) (str " py-4 px-6 gap-1")
+                     compact (str " py-1.5 px-3 gap-0.5")
+                     (not highlighted) (str " "))
+            :ref ref
+            :on-click (when on-click on-click)
+            :on-mouse-over #(set-hover? true)
+            :on-mouse-out #(set-hover? false)
+            :on-mouse-enter (when on-mouse-enter on-mouse-enter)}
+           component-opts)
      ;; header
      (when header
        [:div.text-xs.pl-8.font-light {:class "-mt-1"
@@ -87,9 +88,9 @@
                 :box-shadow (when (#{:gradient} icon-theme) "inset 0 0 0 1px rgba(255,255,255,0.3) ")}
         :class (cond-> "w-5 h-5 rounded flex items-center justify-center"
                  (= icon-theme :color) (str
-                                         " "
-                                         (if highlighted "bg-accent-07-alpha" "bg-gray-05")
-                                         " dark:text-white")
+                                        " "
+                                        (if highlighted "bg-accent-07-alpha" "bg-gray-05")
+                                        " dark:text-white")
                  (= icon-theme :gray) (str " bg-gray-05 dark:text-white"))}
        (shui/tabler-icon icon {:size "14" :class ""})]
       [:div.flex.flex-1.flex-col

+ 4 - 4
src/main/frontend/components/container.cljs

@@ -31,6 +31,7 @@
             [frontend.handler.route :as route-handler]
             [frontend.handler.user :as user-handler]
             [frontend.handler.whiteboard :as whiteboard-handler]
+            [frontend.hooks :as hooks]
             [frontend.mixins :as mixins]
             [frontend.mobile.action-bar :as action-bar]
             [frontend.mobile.footer :as footer]
@@ -424,7 +425,7 @@
        16)
      [])
 
-    (rum/use-layout-effect!
+    (hooks/use-layout-effect!
      (fn []
        (when (and (rum/deref ref-open?) local-closing?)
          (reset! *closing? true))
@@ -498,11 +499,10 @@
                        (storage/set :ls-left-sidebar-width width))]
 
     ;; restore size
-    (rum/use-layout-effect!
+    (hooks/use-layout-effect!
      (fn []
        (when-let [width (storage/get :ls-left-sidebar-width)]
-         (.setProperty (.-style el-doc) "--ls-left-sidebar-width" width)))
-     [])
+         (.setProperty (.-style el-doc) "--ls-left-sidebar-width" width))))
 
     ;; draggable handler
     (rum/use-effect!

+ 3 - 1
src/main/frontend/components/editor.cljs

@@ -19,6 +19,7 @@
             [frontend.handler.paste :as paste-handler]
             [frontend.handler.property.util :as pu]
             [frontend.handler.search :as search-handler]
+            [frontend.hooks :as hooks]
             [frontend.mixins :as mixins]
             [frontend.search :refer [fuzzy-search]]
             [frontend.state :as state]
@@ -146,7 +147,8 @@
                                       (editor-handler/get-matched-classes q)
                                       (editor-handler/<get-matched-blocks q {:nlp-pages? true}))]
                        (set-matched-pages! result))))]
-    (rum/use-effect! search-f [(mixins/use-debounce 50 q)])
+    (rum/use-effect! search-f [(hooks/use-debounced-value q 50)])
+
     (let [matched-pages' (if (string/blank? q)
                            (if db-tag?
                              (db-model/get-all-classes (state/get-current-repo) {:except-root-class? true})

+ 11 - 10
src/main/frontend/components/icon.cljs

@@ -1,22 +1,23 @@
 (ns frontend.components.icon
   (:require ["@emoji-mart/data" :as emoji-data]
             ["emoji-mart" :refer [SearchIndex]]
-            [promesa.core :as p]
-            [cljs-bean.core :as bean]
             [camel-snake-kebab.core :as csk]
+            [cljs-bean.core :as bean]
             [clojure.string :as string]
+            [frontend.config :as config]
+            [frontend.handler.property.util :as pu]
+            [frontend.hooks :as hooks]
             [frontend.search :as search]
             [frontend.storage :as storage]
-            [medley.core :as medley]
-            [rum.core :as rum]
             [frontend.ui :as ui]
-            [logseq.shui.ui :as shui]
             [frontend.util :as util]
-            [goog.object :as gobj]
             [goog.functions :refer [debounce]]
-            [frontend.config :as config]
-            [frontend.handler.property.util :as pu]
-            [logseq.db :as ldb]))
+            [goog.object :as gobj]
+            [logseq.db :as ldb]
+            [logseq.shui.ui :as shui]
+            [medley.core :as medley]
+            [promesa.core :as p]
+            [rum.core :as rum]))
 
 (defonce emojis (vals (bean/->clj (gobj/get emoji-data "emojis"))))
 
@@ -252,7 +253,7 @@
                          (set-current! idx node))
                      (do (.focus (rum/deref *input-ref)) (set-current! -1 nil)))))
         down-handler!
-        (rum/use-callback
+        (hooks/use-callback
          (fn [^js e]
            (let []
              (if (= 13 (.-keyCode e))

+ 2 - 1
src/main/frontend/components/shortcut.cljs

@@ -3,6 +3,7 @@
             [clojure.string :as string]
             [frontend.context.i18n :refer [t]]
             [frontend.handler.notification :as notification]
+            [frontend.hooks :as hooks]
             [frontend.modules.shortcut.config :as shortcut-config]
             [frontend.modules.shortcut.core :as shortcut]
             [frontend.modules.shortcut.data-helper :as dh]
@@ -212,7 +213,7 @@
         [current-binding set-current-binding!] (rum/use-state (or user-binding binding))
         [key-conflicts set-key-conflicts!] (rum/use-state nil)
 
-        handler-id (rum/use-memo #(dh/get-group k))
+        handler-id (hooks/use-memo #(dh/get-group k) [])
         dirty? (not= (or user-binding binding) current-binding)
         keypressed? (not= "" keystroke)
         save-keystroke-fn!

+ 4 - 1
src/main/frontend/extensions/handbooks/core.cljs

@@ -9,6 +9,7 @@
             [frontend.extensions.lightbox :as lightbox]
             [frontend.extensions.video.youtube :as youtube]
             [frontend.handler.notification :as notification]
+            [frontend.hooks :as hooks]
             [frontend.modules.shortcut.config :as shortcut-config]
             [frontend.rum :as r]
             [frontend.search :as search]
@@ -532,7 +533,9 @@
                        (set-active-pane-state! next-state))
 
         [scrolled?, set-scrolled!] (rum/use-state false)
-        on-scroll (rum/use-memo #(util/debounce (fn [^js e] (set-scrolled! (not (< (.. e -target -scrollTop) 10)))) 100) [])]
+        on-scroll (hooks/use-memo
+                   #(util/debounce 100 (fn [^js e] (set-scrolled! (not (< (.. e -target -scrollTop) 10)))))
+                   [])]
 
     ;; load handbooks
     (rum/use-effect!

+ 4 - 3
src/main/frontend/extensions/pdf/core.cljs

@@ -14,6 +14,7 @@
             [frontend.extensions.pdf.windows :as pdf-windows]
             [frontend.handler.notification :as notification]
             [frontend.handler.property :as property-handler]
+            [frontend.hooks :as hooks]
             [frontend.modules.shortcut.core :as shortcut]
             [frontend.rum :refer [use-atom]]
             [frontend.state :as state]
@@ -465,7 +466,7 @@
 
         disable-text-selection! #(js-invoke viewer-clt (if % "add" "remove") "disabled-text-selection")
 
-        fn-move                 (rum/use-callback
+        fn-move                 (hooks/use-callback
                                  (fn [^js/MouseEvent e]
                                    (set-end! (calc-coords! (.-pageX e) (.-pageY e))))
                                  [])]
@@ -549,7 +550,7 @@
         [highlights, set-highlights!] (rum/use-state initial-hls)
         [ctx-menu-state, set-ctx-menu-state!] (rum/use-state {:highlight nil :vw-pos nil :selection nil :point nil :reset-fn nil})
 
-        clear-ctx-menu! (rum/use-callback
+        clear-ctx-menu! (hooks/use-callback
                          #(let [reset-fn (:reset-fn ctx-menu-state)]
                             (set-ctx-menu-state! {})
                             (and (fn? reset-fn) (reset-fn)))
@@ -940,7 +941,7 @@
     ;; cache highlights
     (when-not db-based?
       (let [persist-hls-data!
-            (rum/use-callback
+            (hooks/use-callback
              (util/debounce
               (fn [latest-hls extra]
                 (pdf-assets/file-based-persist-hls-data$

+ 18 - 17
src/main/frontend/extensions/pdf/toolbar.cljs

@@ -2,23 +2,24 @@
   (:require [cljs-bean.core :as bean]
             [clojure.string :as string]
             [frontend.components.svg :as svg]
+            [frontend.config :as config]
             [frontend.context.i18n :refer [t]]
+            [frontend.db.async :as db-async]
+            [frontend.db.conn :as conn]
             [frontend.db.model :as db-model]
+            [frontend.db.utils :as db-utils]
             [frontend.extensions.pdf.assets :as pdf-assets]
             [frontend.extensions.pdf.utils :as pdf-utils]
             [frontend.extensions.pdf.windows :refer [resolve-own-container] :as pdf-windows]
             [frontend.handler.assets :as assets-handler]
             [frontend.handler.notification :as notification]
-            [frontend.config :as config]
-            [frontend.db.conn :as conn]
-            [logseq.publishing.db :as publish-db]
-            [frontend.db.utils :as db-utils]
-            [frontend.db.async :as db-async]
+            [frontend.hooks :as hooks]
             [frontend.rum :refer [use-atom]]
             [frontend.state :as state]
             [frontend.storage :as storage]
             [frontend.ui :as ui]
             [frontend.util :as util]
+            [logseq.publishing.db :as publish-db]
             [logseq.shui.ui :as shui]
             [promesa.core :as p]
             [rum.core :as rum]))
@@ -331,7 +332,7 @@
   (when-let [^js pdf-doc (and viewer (.-pdfDocument viewer))]
     (let [*el-outline       (rum/use-ref nil)
           [outline-data, set-outline-data!] (rum/use-state [])
-          upt-outline-node! (rum/use-callback
+          upt-outline-node! (hooks/use-callback
                              (fn [path attrs]
                                (set-outline-data! (update-in outline-data path merge attrs)))
                              [outline-data])]
@@ -381,16 +382,16 @@
   [repo id]
   (let [[src set-src!] (rum/use-state nil)]
     (rum/use-effect!
-      (fn []
-        (p/let [_ (db-async/<get-block repo id {:children? false})
-                block (db-model/get-block-by-uuid id)]
-          (when-let [asset-path' (and block (publish-db/get-area-block-asset-url
-                                              (conn/get-db (state/get-current-repo))
-                                              block
-                                              (db-utils/pull (:db/id (:block/page block)))))]
-            (-> asset-path' (assets-handler/<make-asset-url)
-              (p/then #(set-src! %))))))
-      [])
+     (fn []
+       (p/let [_ (db-async/<get-block repo id {:children? false})
+               block (db-model/get-block-by-uuid id)]
+         (when-let [asset-path' (and block (publish-db/get-area-block-asset-url
+                                            (conn/get-db (state/get-current-repo))
+                                            block
+                                            (db-utils/pull (:db/id (:block/page block)))))]
+           (-> asset-path' (assets-handler/<make-asset-url)
+               (p/then #(set-src! %))))))
+     [])
 
     (when (string? src)
       [:p.area-wrap [:img {:src src}]])))
@@ -429,7 +430,7 @@
              (if db-graph?
                (area-image-for-db repo id)
                (let [fpath (pdf-assets/resolve-area-image-file
-                             img-stamp (state/get-current-pdf) hl)
+                            img-stamp (state/get-current-pdf) hl)
                      fpath (assets-handler/<make-asset-url fpath)]
                  [:p.area-wrap
                   [:img {:src fpath}]]))

+ 51 - 0
src/main/frontend/hooks.cljs

@@ -0,0 +1,51 @@
+(ns frontend.hooks
+  "React custom hooks."
+  (:refer-clojure :exclude [ref deref])
+  (:require [goog.functions :as gfun]
+            [rum.core :as rum]))
+
+(defn- memo-deps
+  [equal-fn deps]
+  (let [equal-fn (or equal-fn =)
+        ^js deps-ref (rum/use-ref deps)]
+    (when-not (equal-fn (.-current deps-ref) deps)
+      (set! (.-current deps-ref) deps))
+    (.-current deps-ref)))
+
+(defn use-memo
+  [f deps & {:keys [equal-fn]}]
+  (rum/use-memo f #js[(memo-deps equal-fn deps)]))
+
+(defn use-effect!
+  "setup-fn will be invoked every render of component when no deps arg provided"
+  ([setup-fn] (rum/use-effect! setup-fn))
+  ([setup-fn deps & {:keys [equal-fn]}]
+   (rum/use-effect! setup-fn #js[(memo-deps equal-fn deps)])))
+
+(defn use-layout-effect!
+  ([setup-fn] (rum/use-layout-effect! setup-fn))
+  ([setup-fn deps & {:keys [equal-fn]}]
+   (rum/use-layout-effect! setup-fn #js[(memo-deps equal-fn deps)])))
+
+(defn use-callback
+  [callback deps & {:keys [equal-fn]}]
+  (rum/use-callback callback #js[(memo-deps equal-fn deps)]))
+
+;;; unchanged hooks, link to rum/use-xxx directly
+(def use-ref rum/use-ref)
+(def create-ref rum/create-ref)
+(def deref rum/deref)
+(def set-ref! rum/set-ref!)
+(def use-state rum/use-state)
+(comment
+  (def use-reducer rum/use-reducer))
+
+;;; other custom hooks
+
+(defn use-debounced-value
+  "Return the debounced value"
+  [value msec]
+  (let [[debounced-value set-value!] (use-state value)
+        cb (use-callback (gfun/debounce set-value! msec) [])]
+    (use-effect! #(cb value) [value])
+    debounced-value))

+ 3 - 12
src/main/frontend/mixins.cljs

@@ -1,10 +1,9 @@
 (ns frontend.mixins
   "Rum mixins for use in components"
-  (:require [rum.core :as rum]
-            [goog.dom :as dom]
+  (:require [frontend.state :as state]
             [frontend.util :refer [profile] :as util]
-            [frontend.state :as state]
-            [goog.functions :as gfun])
+            [goog.dom :as dom]
+            [rum.core :as rum])
   (:import [goog.events EventHandler]))
 
 (defn detach
@@ -147,11 +146,3 @@
        (profile
         (str "Render " desc)
         (render-fn state))))})
-
-(defn use-debounce
-  "A rumext custom hook that debounces the value changes"
-  [ms value]
-  (let [[state update-fn] (rum/use-state value)
-        update-fn (rum/use-callback (gfun/debounce update-fn ms) [])]
-    (rum/use-effect! #(update-fn value) #js [value])
-    state))