enhance: improve long page loading performance

This commit is contained in:
Tienson Qin
2022-01-08 11:58:39 +08:00
parent fc5a40acb9
commit ca20cbabba
4 changed files with 91 additions and 85 deletions

View File

@@ -88,7 +88,6 @@
(def *move-to (atom nil))
;; TODO: dynamic
(defonce max-blocks-per-page 200)
(defonce max-depth-of-links 5)
(defonce *blocks-container-id (atom 0))
@@ -2886,37 +2885,58 @@
(str (:block/uuid item))))))
(defonce ignore-scroll? (atom false))
(defn- custom-query-or-ref?
[config]
(let [ref? (:ref? config)
custom-query? (:custom-query? config)]
(or custom-query? ref?)))
;; TODO: virtual tree for better UX and memory usage reduce
(def initial-blocks-length 200)
(def step-loading-blocks 50)
(defn- flat-blocks-tree
[vec-tree]
(->> (mapcat (fn [x] (tree-seq map? :block/children x)) vec-tree)
(map #(dissoc % :block/children))))
(defn- get-segment
[config flat-blocks idx blocks->vec-tree]
(let [new-idx (if-not (zero? idx)
(+ idx step-loading-blocks)
initial-blocks-length)
max-idx (count flat-blocks)
idx (min max-idx new-idx)
blocks (util/safe-subvec flat-blocks 0 idx)]
[(blocks->vec-tree blocks)
idx]))
(rum/defcs lazy-blocks <
(rum/local 1 ::page)
[state config blocks]
(let [*page (get state ::page)
segment (->> blocks
(drop (* (dec @*page) max-blocks-per-page))
(take max-blocks-per-page))
{:did-remount (fn [old-state new-state]
;; Loading more when pressing Enter or paste
(let [args (:rum/args new-state)]
;; FIXME: what if users paste too many blocks?
;; or, a template with a lot of blocks?
(swap! (::last-idx new-state) + 100))
new-state)}
(rum/local 0 ::last-idx)
[state config flat-blocks blocks->vec-tree]
(let [*last-idx (::last-idx state)
[segment idx] (get-segment config
flat-blocks
@*last-idx
blocks->vec-tree)
bottom-reached (fn []
(when (and (= (count segment) max-blocks-per-page)
(> (count blocks) (* @*page max-blocks-per-page))
(not @ignore-scroll?))
(swap! *page inc)
(util/scroll-to-top))
(reset! ignore-scroll? false))
top-reached (fn []
(when (> @*page 1)
(swap! *page dec)
(reset! ignore-scroll? true)
(js/setTimeout #(util/scroll-to
(.-scrollHeight (js/document.getElementById "lazy-blocks"))) 100)))]
(reset! *last-idx idx)
(reset! ignore-scroll? false))]
[:div#lazy-blocks
(when (> @*page 1)
[:div.ml-4.mb-4 [:a#prev.opacity-60.opacity-100.text-sm.font-medium {:on-click top-reached}
"Prev"]])
(ui/infinite-list
"main-container"
(block-list config segment)
{:on-load bottom-reached})
(when (> (count blocks) (* @*page max-blocks-per-page))
[:div.ml-4.mt-4 [:a#more.opacity-60.opacity-100.text-sm.font-medium {:on-click bottom-reached}
"More"]])]))
{:on-load bottom-reached
:threhold 400})]))
(rum/defcs blocks-container <
{:init (fn [state]
@@ -2928,20 +2948,19 @@
(let [id' (swap! *blocks-container-id inc)]
(reset! *init-blocks-container-id id')
id'))
sidebar? (:sidebar? config)
ref? (:ref? config)
custom-query? (:custom-query? config)
blocks->vec-tree #(if (or custom-query? ref?) % (tree/blocks->vec-tree % (:id config)))
blocks' (blocks->vec-tree blocks)
blocks (if (seq blocks') blocks' blocks)
config (assoc config :blocks-container-id blocks-container-id)
doc-mode? (:document/mode? config)]
(when (seq blocks)
[:div.blocks-container.flex-1
{:class (when doc-mode? "document-mode")
;; :style {:margin-left (if sidebar? 0 -10)}
}
(lazy-blocks config blocks)])))
(let [blocks->vec-tree #(if (custom-query-or-ref? config) % (tree/blocks->vec-tree % (:id config)))
blocks-tree (blocks->vec-tree blocks)
blocks-tree (if (seq blocks-tree) blocks-tree blocks)
flat-blocks (if (custom-query-or-ref? config)
blocks-tree
(flat-blocks-tree blocks-tree))
flat-blocks (vec flat-blocks)]
[:div.blocks-container.flex-1
{:class (when doc-mode? "document-mode")}
(lazy-blocks config flat-blocks blocks->vec-tree)]))))
;; headers to hiccup
(defn ->hiccup