fix: drag drop on non consecutive blocks

close #5267
This commit is contained in:
Tienson Qin
2022-05-21 23:23:30 +08:00
parent e3fa589396
commit eb42972ef9
3 changed files with 122 additions and 21 deletions

View File

@@ -29,7 +29,8 @@
:source-map true
:externs ["datascript/externs.js"
"externs.js"]
:warnings {:fn-deprecated false}}
:warnings {:fn-deprecated false
:redef false}}
:closure-defines {goog.debug.LOGGING_ENABLED true}
;; NOTE: electron, browser/mobile-app use different asset-paths.
@@ -54,7 +55,8 @@
:externs ["datascript/externs.js"
"externs.js"]
:warnings {:fn-deprecated false}}}
:warnings {:fn-deprecated false
:redef false}}}
:test {:target :node-test
:output-to "static/tests.js"
@@ -86,7 +88,8 @@
:output-feature-set :es-next
:externs ["datascript/externs.js"
"externs.js"]
:warnings {:fn-deprecated false}}
:warnings {:fn-deprecated false
:redef false}}
:devtools {:before-load frontend.core/stop
:after-load frontend.core/start
:preloads [devtools.preload]}}

View File

@@ -409,6 +409,29 @@
f))
form))
(defn get-sorted-page-block-ids
[page-id]
(let [root (db-utils/entity page-id)]
(loop [result []
children (sort-by-left (:block/_parent root) root)]
(if (seq children)
(let [child (first children)]
(recur (conj result (:db/id child))
(concat
(sort-by-left (:block/_parent child) child)
(rest children))))
result))))
(defn sort-page-random-blocks
"Blocks could be non consecutive."
[blocks]
(assert (every? #(= (:block/page %) (:block/page (first blocks))) blocks) "Blocks must to be in a same page.")
(let [page-id (:db/id (:block/page (first blocks)))
;; TODO: there's no need to sort all the blocks
sorted-ids (get-sorted-page-block-ids page-id)
blocks-map (zipmap (map :db/id blocks) blocks)]
(keep blocks-map sorted-ids)))
(defn has-children?
([block-id]
(has-children? (conn/get-db) block-id))
@@ -584,6 +607,57 @@
(recur parent)))
false)))))
(defn get-prev-sibling
[db id]
(when-let [e (d/entity db id)]
(let [left (:block/left e)]
(when (not= (:db/id left) (:db/id (:block/parent e)))
left))))
(defn get-right-sibling
[db db-id]
(when-let [block (d/entity db db-id)]
(get-by-parent-&-left db
(:db/id (:block/parent block))
db-id)))
(defn last-child-block?
"The child block could be collapsed."
[db parent-id child-id]
(when-let [child (d/entity db child-id)]
(cond
(= parent-id child-id)
true
(get-right-sibling db child-id)
false
:else
(last-child-block? db parent-id (:db/id (:block/parent child))))))
(defn- consecutive-block?
[block-1 block-2]
(let [db (conn/get-db)
aux-fn (fn [block-1 block-2]
(and (= (:block/page block-1) (:block/page block-2))
(or
;; sibling or child
(= (:db/id (:block/left block-2)) (:db/id block-1))
(when-let [prev-sibling (get-prev-sibling db (:db/id block-2))]
(last-child-block? db (:db/id prev-sibling) (:db/id block-1))))))]
(or (aux-fn block-1 block-2) (aux-fn block-2 block-1))))
(defn get-non-consecutive-blocks
[blocks]
(vec
(keep-indexed
(fn [i _block]
(when (< (inc i) (count blocks))
(when-not (consecutive-block? (nth blocks i)
(nth blocks (inc i)))
(nth blocks i))))
blocks)))
(defn- get-start-id-for-pagination-query
[repo-url current-db {:keys [db-before tx-meta] :as tx-report}
result outliner-op page-id block-id tx-block-ids]

View File

@@ -99,7 +99,7 @@
(-get-parent-id [this]
(-> (get-in this [:data :block/parent])
(outliner-u/->block-id)))
(outliner-u/->block-id)))
(-set-parent-id [this parent-id]
(outliner-u/check-block-id parent-id)
@@ -107,7 +107,7 @@
(-get-left-id [this]
(-> (get-in this [:data :block/left])
(outliner-u/->block-id)))
(outliner-u/->block-id)))
(-set-left-id [this left-id]
(outliner-u/check-block-id left-id)
@@ -170,7 +170,7 @@
(-del [this txs-state children?]
(assert (ds/outliner-txs-state? txs-state)
"db should be satisfied outliner-tx-state?")
"db should be satisfied outliner-tx-state?")
(let [block-id (tree/-get-id this)
ids (set (if children?
(let [children (db/get-block-children (state/get-current-repo) block-id)
@@ -192,7 +192,7 @@
(assoc :block/left parent))))
immediate-children)))
txs))
txs)]
txs)]
(swap! txs-state concat txs)
block-id))
@@ -209,12 +209,7 @@
(defn get-right-sibling
[db-id]
(when db-id
(when-let [block (db/entity db-id)]
(db-model/get-by-parent-&-left (conn/get-db)
(:db/id (:block/parent block))
db-id))))
(db-model/get-right-sibling (conn/get-db) db-id)))
(defn- assoc-level-aux
[tree-vec children-key init-level]
@@ -285,13 +280,13 @@
(loop [node node
limit limit
result []]
(if (zero? limit)
result
(if-let [left (tree/-get-left node)]
(if-not (= left parent)
(recur left (dec limit) (conj result (tree/-get-id left)))
result)
result)))))
(if (zero? limit)
result
(if-let [left (tree/-get-left node)]
(if-not (= left parent)
(recur left (dec limit) (conj result (tree/-get-id left)))
result)
result)))))
(defn- page-first-child?
[block]
@@ -573,6 +568,34 @@
(recur (:block/left (get id->blocks (:db/id block))))
(:db/id block)))})))
(defn find-new-left
[block moved-ids target-block current-block sibling?]
(if (= (:db/id target-block) (:db/id (:block/left current-block)))
(if sibling?
(db/entity (last moved-ids))
target-block)
(let [left (db/entity (:db/id (:block/left block)))]
(if (contains? (set moved-ids) (:db/id left))
(find-new-left left moved-ids target-block current-block sibling?)
left))))
(defn- fix-non-consecutive-blocks
[blocks target-block sibling?]
(let [page-blocks (group-by :block/page blocks)]
(->>
(mapcat (fn [[_page blocks]]
(let [blocks (db-model/sort-page-random-blocks blocks)
non-consecutive-blocks (->> (conj (db-model/get-non-consecutive-blocks blocks) (last blocks))
(util/distinct-by :db/id))]
(when (seq non-consecutive-blocks)
(mapv (fn [block]
(when-let [right (get-right-sibling (:db/id block))]
(when-let [new-left (find-new-left right (distinct (map :db/id blocks)) target-block block sibling?)]
{:db/id (:db/id right)
:block/left (:db/id new-left)})))
non-consecutive-blocks)))) page-blocks)
(remove nil?))))
(defn move-blocks
"Move `blocks` to `target-block` as siblings or children."
[blocks target-block {:keys [sibling? outliner-op]}]
@@ -598,7 +621,8 @@
(let [children-ids (mapcat #(db/get-block-children-ids (state/get-current-repo) (:block/uuid %)) blocks)]
(map (fn [uuid] {:block/uuid uuid
:block/page target-page}) children-ids)))
full-tx (util/concat-without-nil tx-data move-blocks-next-tx children-page-tx)
fix-non-consecutive-tx (fix-non-consecutive-blocks blocks target-block sibling?)
full-tx (util/concat-without-nil tx-data move-blocks-next-tx children-page-tx fix-non-consecutive-tx)
tx-meta (cond-> {:move-blocks (mapv :db/id blocks)
:target (:db/id target-block)}
not-same-page?