mirror of
https://github.com/logseq/logseq.git
synced 2026-05-19 10:22:37 +00:00
fix(ux): incorrect reaction for the order list sibling blocks (#12617)
* fix(ux): incorrect reaction for the order list sibling blocks * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix: lint * chore(test): add tests for order list type and sibling block interactions * fix: refresh nested ordered lists * fix: split affected query keys helper --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
"Compute reactive query affected keys"
|
||||
(:require [cljs.spec.alpha :as s]
|
||||
[datascript.core :as d]
|
||||
[logseq.common.util :as common-util]))
|
||||
[logseq.common.util :as common-util]
|
||||
[logseq.db.frontend.property :as db-property]))
|
||||
|
||||
;;; keywords specs for reactive query, used by `react/q` calls
|
||||
;; ::block
|
||||
@@ -41,6 +42,96 @@
|
||||
(= journal-tag-id (:db/id tag)))
|
||||
(:block/tags (d/entity db eid)))))
|
||||
|
||||
(def ^:private block-query-affecting-attrs
|
||||
#{:logseq.property/order-list-type})
|
||||
|
||||
(def ^:private order-list-affecting-attrs
|
||||
#{:block/parent :block/page :block/order :logseq.property/order-list-type})
|
||||
|
||||
(defn- block-attr?
|
||||
[attr]
|
||||
(= "block" (namespace attr)))
|
||||
|
||||
(defn- block-query-affecting-attr?
|
||||
[attr]
|
||||
(or (block-attr? attr)
|
||||
(contains? block-query-affecting-attrs attr)))
|
||||
|
||||
(defn- block-key
|
||||
[block]
|
||||
[::block (:db/id block)])
|
||||
|
||||
(defn- order-list-type
|
||||
[block]
|
||||
(db-property/lookup block :logseq.property/order-list-type))
|
||||
|
||||
(defn- sibling-entities
|
||||
[block]
|
||||
(cond
|
||||
(:block/parent block)
|
||||
(some-> (:block/parent block) :block/_parent)
|
||||
|
||||
(:block/page block)
|
||||
(some-> (:block/page block) :block/_page)
|
||||
|
||||
:else
|
||||
nil))
|
||||
|
||||
(defn- ordered-siblings
|
||||
[block]
|
||||
(some->> (sibling-entities block)
|
||||
(sort-by :block/order)))
|
||||
|
||||
(defn- right-ordered-siblings
|
||||
[block]
|
||||
(when-let [siblings (seq (ordered-siblings block))]
|
||||
(->> siblings
|
||||
(drop-while #(not= (:db/id %) (:db/id block)))
|
||||
rest)))
|
||||
|
||||
(defn- collect-right-order-list-sibling-keys
|
||||
[siblings target-order-list-type]
|
||||
(when target-order-list-type
|
||||
(->> siblings
|
||||
(take-while #(= target-order-list-type (order-list-type %)))
|
||||
(map block-key))))
|
||||
|
||||
(defn- affected-right-order-list-sibling-keys
|
||||
[db block-id]
|
||||
(when-let [block (and db (d/entity db block-id))]
|
||||
(let [right-siblings (right-ordered-siblings block)
|
||||
right-sibling (first right-siblings)]
|
||||
(concat
|
||||
(collect-right-order-list-sibling-keys right-siblings (order-list-type block))
|
||||
(collect-right-order-list-sibling-keys right-siblings (order-list-type right-sibling))))))
|
||||
|
||||
(defn- affected-order-list-descendant-keys
|
||||
[db block-id]
|
||||
(when-let [block (and db (d/entity db block-id))]
|
||||
(letfn [(collect [parent]
|
||||
(when-let [parent-list-type (order-list-type parent)]
|
||||
(mapcat
|
||||
(fn [child]
|
||||
(when (= parent-list-type (order-list-type child))
|
||||
(cons (block-key child) (collect child))))
|
||||
(:block/_parent parent))))]
|
||||
(collect block))))
|
||||
|
||||
(defn- affected-block-keys
|
||||
[block]
|
||||
(let [page-id (or
|
||||
(when (:block/name block) (:db/id block))
|
||||
(:db/id (:block/page block)))
|
||||
blocks [(when-let [parent-id (:db/id (:block/parent block))]
|
||||
[::block parent-id])
|
||||
[::block (:db/id block)]]
|
||||
refs (->> (keep (fn [ref]
|
||||
(when-not (= (:db/id ref) page-id)
|
||||
[[::refs (:db/id ref)]
|
||||
[::block (:db/id ref)]])) (:block/refs block))
|
||||
(apply concat))]
|
||||
(concat blocks refs)))
|
||||
|
||||
(defn get-affected-queries-keys
|
||||
"Get affected queries through transaction datoms."
|
||||
[{:keys [tx-data db-before db-after]}]
|
||||
@@ -77,8 +168,12 @@
|
||||
recycle-roots? (some (fn [datom]
|
||||
(= :logseq.property/deleted-at (:a datom)))
|
||||
tx-data)
|
||||
other-blocks (->> (filter (fn [datom] (= "block" (namespace (:a datom)))) tx-data)
|
||||
other-blocks (->> (filter (fn [datom] (block-query-affecting-attr? (:a datom))) tx-data)
|
||||
(map :e))
|
||||
order-list-affected-blocks (->> (filter (fn [datom]
|
||||
(contains? order-list-affecting-attrs (:a datom))) tx-data)
|
||||
(map :e)
|
||||
(distinct))
|
||||
blocks (-> (concat blocks other-blocks) distinct)
|
||||
block-entities (keep (fn [block-id]
|
||||
(let [block-id (if (and (string? block-id) (common-util/uuid-string? block-id))
|
||||
@@ -87,20 +182,7 @@
|
||||
(d/entity db-after block-id))) blocks)
|
||||
affected-keys (concat
|
||||
(mapcat
|
||||
(fn [block]
|
||||
(let [page-id (or
|
||||
(when (:block/name block) (:db/id block))
|
||||
(:db/id (:block/page block)))
|
||||
blocks [(when-let [parent-id (:db/id (:block/parent block))]
|
||||
[::block parent-id])
|
||||
[::block (:db/id block)]]
|
||||
block-refs (:block/refs block)
|
||||
refs (->> (keep (fn [ref]
|
||||
(when-not (= (:db/id ref) page-id)
|
||||
[[::refs (:db/id ref)]
|
||||
[::block (:db/id ref)]])) block-refs)
|
||||
(apply concat))]
|
||||
(concat blocks refs)))
|
||||
affected-block-keys
|
||||
block-entities)
|
||||
|
||||
(mapcat
|
||||
@@ -115,6 +197,15 @@
|
||||
[::block target-id]])
|
||||
reaction-targets)
|
||||
|
||||
(mapcat
|
||||
(fn [block-id]
|
||||
(concat
|
||||
(affected-right-order-list-sibling-keys db-before block-id)
|
||||
(affected-right-order-list-sibling-keys db-after block-id)
|
||||
(affected-order-list-descendant-keys db-before block-id)
|
||||
(affected-order-list-descendant-keys db-after block-id)))
|
||||
order-list-affected-blocks)
|
||||
|
||||
(keep
|
||||
(fn [tag]
|
||||
(when tag [::objects tag]))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
[datascript.core :as d]
|
||||
[frontend.worker.react :as worker-react]
|
||||
[logseq.db.common.order :as db-order]
|
||||
[logseq.db.test.helper :as db-test]))
|
||||
|
||||
(deftest affected-keys-block-reactions
|
||||
@@ -20,6 +21,66 @@
|
||||
affected (worker-react/get-affected-queries-keys tx-report)]
|
||||
(is (some #{[:frontend.worker.react/block-reactions target-id]} affected)))))
|
||||
|
||||
(deftest affected-keys-order-list-type
|
||||
(testing "changing order list type affects block query key"
|
||||
(let [conn (db-test/create-conn-with-blocks
|
||||
[{:page {:block/title "Test"}
|
||||
:blocks [{:block/title "Block"
|
||||
:build/properties {:logseq.property/order-list-type "number"}}]}])
|
||||
block (db-test/find-block-by-content @conn "Block")
|
||||
target-id (:db/id block)
|
||||
tx-report (d/transact! conn
|
||||
[[:db/retract target-id :logseq.property/order-list-type
|
||||
(:db/id (:logseq.property/order-list-type block))]])
|
||||
affected (worker-react/get-affected-queries-keys tx-report)]
|
||||
(is (some #{[:frontend.worker.react/block target-id]} affected)))))
|
||||
|
||||
(deftest affected-keys-order-list-right-siblings
|
||||
(testing "inserting a block before ordered-list siblings affects their block query keys"
|
||||
(let [conn (db-test/create-conn-with-blocks
|
||||
[{:page {:block/title "Test"}
|
||||
:blocks [{:block/title "Block 1"
|
||||
:build/properties {:logseq.property/order-list-type "number"}}
|
||||
{:block/title "Block 2"
|
||||
:build/properties {:logseq.property/order-list-type "number"}}
|
||||
{:block/title "Block 3"
|
||||
:build/properties {:logseq.property/order-list-type "number"}}]}])
|
||||
block-1 (db-test/find-block-by-content @conn "Block 1")
|
||||
block-2 (db-test/find-block-by-content @conn "Block 2")
|
||||
block-3 (db-test/find-block-by-content @conn "Block 3")
|
||||
tx-report (d/transact! conn
|
||||
[{:block/uuid (random-uuid)
|
||||
:block/title "Inserted"
|
||||
:block/page (:db/id (:block/page block-1))
|
||||
:block/parent (:db/id (:block/parent block-1))
|
||||
:block/order (db-order/gen-key (:block/order block-1)
|
||||
(:block/order block-2))
|
||||
:block/created-at 1
|
||||
:block/updated-at 1}])
|
||||
affected (worker-react/get-affected-queries-keys tx-report)]
|
||||
(is (some #{[:frontend.worker.react/block (:db/id block-2)]} affected))
|
||||
(is (some #{[:frontend.worker.react/block (:db/id block-3)]} affected)))))
|
||||
|
||||
(deftest affected-keys-order-list-descendants
|
||||
(testing "changing ordered-list parent type affects nested ordered-list descendants"
|
||||
(let [conn (db-test/create-conn-with-blocks
|
||||
[{:page {:block/title "Test"}
|
||||
:blocks [{:block/title "Parent"
|
||||
:build/properties {:logseq.property/order-list-type "number"}
|
||||
:build/children [{:block/title "Child"
|
||||
:build/properties {:logseq.property/order-list-type "number"}
|
||||
:build/children [{:block/title "Grandchild"
|
||||
:build/properties {:logseq.property/order-list-type "number"}}]}]}]}])
|
||||
parent (db-test/find-block-by-content @conn "Parent")
|
||||
child (db-test/find-block-by-content @conn "Child")
|
||||
grandchild (db-test/find-block-by-content @conn "Grandchild")
|
||||
tx-report (d/transact! conn
|
||||
[[:db/retract (:db/id parent) :logseq.property/order-list-type
|
||||
(:db/id (:logseq.property/order-list-type parent))]])
|
||||
affected (worker-react/get-affected-queries-keys tx-report)]
|
||||
(is (some #{[:frontend.worker.react/block (:db/id child)]} affected))
|
||||
(is (some #{[:frontend.worker.react/block (:db/id grandchild)]} affected)))))
|
||||
|
||||
(deftest affected-keys-journals-when-journal-recycled
|
||||
(testing "recycling a journal page should refresh journals query key"
|
||||
(let [conn (db-test/create-conn-with-blocks
|
||||
|
||||
Reference in New Issue
Block a user