feat: virtual list

pull/4750/head
Tienson Qin 2022-03-29 03:14:27 +08:00
parent af6e727071
commit bfae3f07d4
6 changed files with 75 additions and 44 deletions

View File

@ -110,6 +110,7 @@
"react-textarea-autosize": "8.3.3",
"react-tippy": "1.4.0",
"react-transition-group": "4.3.0",
"react-virtuoso": "^2.8.5",
"reakit": "0.11.1",
"remove-accents": "0.4.2",
"send-intent": "3.0.11",

View File

@ -2238,7 +2238,8 @@
(when pre-block? " pre-block")
(when (and card? (not review-cards?)) " shadow-xl"))
:blockid (str uuid)
:haschild (str has-child?)}
:haschild (str has-child?)
:style {:padding-left (* (- level 1) 24)}}
level
(assoc :level level)
@ -2274,7 +2275,7 @@
(block-content-or-editor config block edit-input-id block-id heading-level edit?)]
(block-children config children collapsed?)
;; (block-children config children collapsed?)
(dnd-separator-wrapper block block-id slide? false false)]))
@ -2846,16 +2847,20 @@
[config col]
(map #(markup-element-cp config %) col))
(defn- block-item
[config blocks idx item]
(let [item (->
(dissoc item :block/meta)
(assoc :block/top? (zero? idx)
:block/bottom? (= (count blocks) (inc idx))))
config (assoc config :block/uuid (:block/uuid item))]
(rum/with-key (block-container config item)
(str (:block/uuid item)))))
(defn- block-list
[config blocks]
(for [[idx item] (medley/indexed blocks)]
(let [item (->
(dissoc item :block/meta)
(assoc :block/top? (zero? idx)
:block/bottom? (= (count blocks) (inc idx))))
config (assoc config :block/uuid (:block/uuid item))]
(rum/with-key (block-container config item)
(str (:block/uuid item))))))
(block-item config blocks idx item)))
(defn- custom-query-or-ref?
[config]
@ -2863,8 +2868,6 @@
custom-query? (:custom-query? config)]
(or custom-query? ref?)))
;; TODO: virtual tree for better UX and memory usage reduce
(defn- load-more-blocks!
[config flat-blocks]
(when-let [db-id (:db/id config)]
@ -2874,33 +2877,20 @@
(rum/defcs lazy-blocks < rum/reactive
{:init (fn [state]
(assoc state ::id (str (random-uuid))))}
[state config flat-blocks blocks->vec-tree]
(let [db-id (:db/id config)
blocks (blocks->vec-tree flat-blocks)]
(if (:custom-query? config)
(block-list config blocks)
(let [last-block-id (:db/id (last flat-blocks))
bottom-reached (fn []
(when (and db-id
;; To prevent scrolling after inserting new blocks
(> (- (util/time-ms) (:start-time config)) 200))
(load-more-blocks! config flat-blocks)))
has-more? (when db-id
(and (not= last-block-id (model/get-block-last-child db-id))
(not= last-block-id db-id)))
dom-id (str "lazy-blocks-" (::id state))]
[:div {:id dom-id}
(ui/infinite-list
"main-content-container"
(block-list config blocks)
{:on-load bottom-reached
:bottom-reached (fn []
(when-let [node (gdom/getElement dom-id)]
(ui/bottom-reached? node 1000)))
:has-more has-more?
:more (if (or (:preview? config) (:sidebar? config))
"More"
(ui/loading "Loading"))})]))))
[state config blocks blocks->vec-tree]
(let [db-id (:db/id config)]
(if (or (:custom-query? config) (not db-id))
(let [blocks (blocks->vec-tree blocks)]
(block-list config blocks))
(let [blocks (tree/blocks-with-level blocks)
bottom-reached (fn [] (load-more-blocks! config blocks))]
(ui/virtual-list {:style {:height "calc(100vh - 180px)"}
:data (bean/->js blocks)
:end-reached bottom-reached
:overscan 200
:item-content (fn [idx block]
(let [block (bean/->clj block)]
(block-item config blocks idx block)))})))))
(rum/defcs blocks-container <
{:init (fn [state]

View File

@ -53,12 +53,13 @@
(defn sync-to-file
[{page-db-id :db/id}]
(if (nil? page-db-id)
(notification/show!
"Write file failed, can't find the current page!"
:error)
(when-let [repo (state/get-current-repo)]
(async/put! write-chan [repo page-db-id]))))
;; (if (nil? page-db-id)
;; (notification/show!
;; "Write file failed, can't find the current page!"
;; :error)
;; (when-let [repo (state/get-current-repo)]
;; (async/put! write-chan [repo page-db-id])))
)
(util/batch write-chan
batch-write-interval

View File

@ -80,3 +80,20 @@
[blocks-exclude-root root]
(let [parent-groups (atom (group-by :block/parent blocks-exclude-root))]
(flatten (concat (sort-blocks-aux [root] parent-groups) (vals @parent-groups)))))
(defn blocks-with-level
"`blocks` should be sorted already."
[blocks]
(let [level->block (atom {})]
(loop [blocks blocks
result []]
(if-let [block (first blocks)]
(let [parent-id (:db/id (:block/parent block))
parent-level (get @level->block parent-id)
level' (inc (or parent-level 0))
block (assoc block :block/level level')]
(when-not parent-level
(swap! level->block assoc parent-id parent-level))
(swap! level->block assoc (:db/id block) level')
(recur (rest blocks) (conj result block)))
result))))

View File

@ -24,6 +24,7 @@
["react-textarea-autosize" :as TextareaAutosize]
["react-tippy" :as react-tippy]
["react-transition-group" :refer [CSSTransition TransitionGroup]]
["react-virtuoso" :refer [Virtuoso]]
["@logseq/react-tweet-embed" :as react-tweet-embed]
[rum.core :as rum]
[frontend.db-mixins :as db-mixins]
@ -33,6 +34,7 @@
(defonce transition-group (r/adapt-class TransitionGroup))
(defonce css-transition (r/adapt-class CSSTransition))
(defonce textarea (r/adapt-class (gobj/get TextareaAutosize "default")))
(defonce virtual-list (r/adapt-class Virtuoso))
(def resize-provider (r/adapt-class (gobj/get Resize "ResizeProvider")))
(def resize-consumer (r/adapt-class (gobj/get Resize "ResizeConsumer")))
(def Tippy (r/adapt-class (gobj/get react-tippy "Tooltip")))

View File

@ -1271,6 +1271,18 @@
dependencies:
"@types/node" "*"
"@virtuoso.dev/react-urx@^0.2.12":
version "0.2.13"
resolved "https://registry.yarnpkg.com/@virtuoso.dev/react-urx/-/react-urx-0.2.13.tgz#e2cfc42d259d2a002695e7517d34cb97b64ee9c4"
integrity sha512-MY0ugBDjFb5Xt8v2HY7MKcRGqw/3gTpMlLXId2EwQvYJoC8sP7nnXjAxcBtTB50KTZhO0SbzsFimaZ7pSdApwA==
dependencies:
"@virtuoso.dev/urx" "^0.2.13"
"@virtuoso.dev/urx@^0.2.12", "@virtuoso.dev/urx@^0.2.13":
version "0.2.13"
resolved "https://registry.yarnpkg.com/@virtuoso.dev/urx/-/urx-0.2.13.tgz#a65e7e8d923cb03397ac876bfdd45c7f71c8edf1"
integrity sha512-iirJNv92A1ZWxoOHHDYW/1KPoi83939o83iUBQHIim0i3tMeSKEh+bxhJdTHQ86Mr4uXx9xGUTq69cp52ZP8Xw==
acorn-node@^1.6.1:
version "1.8.2"
resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8"
@ -6826,6 +6838,14 @@ react-transition-group@4.3.0:
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-virtuoso@^2.8.5:
version "2.8.5"
resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-2.8.5.tgz#92f22d22255b444380dd0a29004d9bf678df834a"
integrity sha512-ayFESqgt++or9NLZ5XZR9Pta5W9jiT9pf9cYa/FYX5BoDuWMFYhou7xCal624JY6CzOOnwUlCGck95dtxsVDiA==
dependencies:
"@virtuoso.dev/react-urx" "^0.2.12"
"@virtuoso.dev/urx" "^0.2.12"
react@17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"