mirror of
https://github.com/logseq/logseq.git
synced 2026-05-28 14:39:48 +00:00
Merge remote-tracking branch 'upstream/master' into whiteboards
This commit is contained in:
@@ -2404,7 +2404,6 @@
|
||||
(when (and
|
||||
(state/in-selection-mode?)
|
||||
(non-dragging? e))
|
||||
(util/stop e)
|
||||
(editor-handler/highlight-selection-area! block-id))))
|
||||
|
||||
(defn- block-mouse-leave
|
||||
@@ -2463,7 +2462,9 @@
|
||||
*navigating-block (get state ::navigating-block)
|
||||
navigating-block (rum/react *navigating-block)
|
||||
navigated? (and (not= (:block/uuid block) navigating-block) navigating-block)
|
||||
block (if (or navigated? custom-query?)
|
||||
block (if (or navigated?
|
||||
custom-query?
|
||||
(and ref? (:block/uuid config)))
|
||||
(let [block (db/pull [:block/uuid navigating-block])
|
||||
blocks (db/get-paginated-blocks repo (:db/id block)
|
||||
{:scoped-block-id (:db/id block)})
|
||||
@@ -2508,8 +2509,7 @@
|
||||
edit? (state/sub [:editor/editing? edit-input-id])
|
||||
card? (string/includes? data-refs-self "\"card\"")
|
||||
review-cards? (:review-cards? config)
|
||||
selected-blocks (set (state/get-selection-block-ids))
|
||||
selected? (contains? selected-blocks uuid)]
|
||||
selected? (state/sub-block-selected? uuid)]
|
||||
[:div.ls-block
|
||||
(cond->
|
||||
{:id block-id
|
||||
@@ -2848,7 +2848,8 @@
|
||||
(let [dsl-query? (:dsl-query? config)
|
||||
query-atom (:query-atom state)
|
||||
repo (state/get-current-repo)
|
||||
query-time (react/get-query-time query)
|
||||
query-time (or (react/get-query-time query)
|
||||
(react/get-query-time q))
|
||||
view-fn (if (keyword? view) (state/sub [:config repo :query/views view]) view)
|
||||
current-block-uuid (or (:block/uuid (:block config))
|
||||
(:block/uuid config))
|
||||
@@ -3331,7 +3332,7 @@
|
||||
{:class (when doc-mode? "document-mode")}
|
||||
(lazy-blocks config blocks' flat-blocks)]))))
|
||||
|
||||
(rum/defcs breadcrumb-with-container < rum/reactive
|
||||
(rum/defcs breadcrumb-with-container < rum/reactive db-mixins/query
|
||||
{:init (fn [state]
|
||||
(let [first-block (ffirst (:rum/args state))]
|
||||
(assoc state
|
||||
|
||||
@@ -359,7 +359,7 @@
|
||||
(block-ref-custom-context-menu-content block block-ref))
|
||||
(state/set-state! :block-ref/context nil))
|
||||
|
||||
(state/selection?)
|
||||
(and (state/selection?) (not (d/has-class? target "bullet")))
|
||||
(common-handler/show-custom-context-menu!
|
||||
e
|
||||
(custom-context-menu-content))
|
||||
|
||||
@@ -302,8 +302,12 @@
|
||||
(let [[_id on-submit] (:rum/args state)
|
||||
command (:command (first input-option))]
|
||||
(on-submit command @input-value))
|
||||
(reset! input-value nil))))})))
|
||||
[state _id on-submit]
|
||||
(reset! input-value nil))))
|
||||
;; escape
|
||||
27 (fn [_state _e]
|
||||
(let [[id _on-submit on-cancel] (:rum/args state)]
|
||||
(on-cancel id)))})))
|
||||
[state _id on-submit _on-cancel]
|
||||
(when (= :input (state/sub :editor/action))
|
||||
(when-let [action-data (state/sub :editor/action-data)]
|
||||
(let [{:keys [pos options]} action-data
|
||||
@@ -335,7 +339,7 @@
|
||||
(on-submit command @input-value pos)))]))))))
|
||||
|
||||
(rum/defc absolute-modal < rum/static
|
||||
[cp set-default-width? {:keys [top left rect]}]
|
||||
[cp modal-name set-default-width? {:keys [top left rect]}]
|
||||
(let [max-height 370
|
||||
max-width 300
|
||||
offset-top 24
|
||||
@@ -380,6 +384,7 @@
|
||||
{:left (if (or (nil? y-diff) (and y-diff (= y-diff 0))) left 0)})))]
|
||||
[:div.absolute.rounded-md.shadow-lg.absolute-modal
|
||||
{:ref *el
|
||||
:data-modal-name modal-name
|
||||
:class (if y-overflow-vh? "is-overflow-vh-y" "")
|
||||
:on-mouse-down (fn [e]
|
||||
(.stopPropagation e))
|
||||
@@ -387,13 +392,13 @@
|
||||
cp]))
|
||||
|
||||
(rum/defc transition-cp < rum/reactive
|
||||
[cp set-default-width?]
|
||||
[cp modal-name set-default-width?]
|
||||
(when-let [pos (:pos (state/sub :editor/action-data))]
|
||||
(ui/css-transition
|
||||
{:class-names "fade"
|
||||
:timeout {:enter 500
|
||||
:exit 300}}
|
||||
(absolute-modal cp set-default-width? pos))))
|
||||
(absolute-modal cp modal-name set-default-width? pos))))
|
||||
|
||||
(rum/defc image-uploader < rum/reactive
|
||||
[id format]
|
||||
@@ -412,6 +417,7 @@
|
||||
[:div.flex.flex-row.align-center.rounded-md.shadow-sm.bg-base-2.px-1.py-1
|
||||
(ui/loading
|
||||
(util/format "Uploading %s%" (util/format "%2d" processing)))]
|
||||
"upload-file"
|
||||
false)))])
|
||||
|
||||
(defn- set-up-key-down!
|
||||
@@ -422,11 +428,11 @@
|
||||
{:not-matched-handler (editor-handler/keydown-not-matched-handler format)}))
|
||||
|
||||
(defn- set-up-key-up!
|
||||
[state input input-id search-timeout]
|
||||
[state input input-id]
|
||||
(mixins/on-key-up
|
||||
state
|
||||
{}
|
||||
(editor-handler/keyup-handler state input input-id search-timeout)))
|
||||
(editor-handler/keyup-handler state input input-id)))
|
||||
|
||||
(def search-timeout (atom nil))
|
||||
|
||||
@@ -436,7 +442,7 @@
|
||||
input-id id
|
||||
input (gdom/getElement input-id)]
|
||||
(set-up-key-down! state format)
|
||||
(set-up-key-up! state input input-id search-timeout)))
|
||||
(set-up-key-up! state input input-id)))
|
||||
|
||||
(def starts-with? clojure.string/starts-with?)
|
||||
|
||||
@@ -510,10 +516,10 @@
|
||||
(mock-textarea content)))
|
||||
|
||||
(rum/defc animated-modal < rum/reactive
|
||||
[key component set-default-width?]
|
||||
[modal-name component set-default-width?]
|
||||
(when-let [pos (:pos (state/get-editor-action-data))]
|
||||
(ui/css-transition
|
||||
{:key key
|
||||
{:key modal-name
|
||||
:class-names {:enter "origin-top-left opacity-0 transform scale-95"
|
||||
:enter-done "origin-top-left transition opacity-100 transform scale-100"
|
||||
:exit "origin-top-left transition opacity-0 transform scale-95"}
|
||||
@@ -522,6 +528,7 @@
|
||||
(fn [_]
|
||||
(absolute-modal
|
||||
component
|
||||
modal-name
|
||||
set-default-width?
|
||||
pos)))))
|
||||
|
||||
@@ -557,7 +564,9 @@
|
||||
(= :input action)
|
||||
(animated-modal "input" (input id
|
||||
(fn [command m]
|
||||
(editor-handler/handle-command-input command id format m)))
|
||||
(editor-handler/handle-command-input command id format m))
|
||||
(fn []
|
||||
(editor-handler/handle-command-input-close id)))
|
||||
true)
|
||||
|
||||
(= :zotero action)
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
|
||||
(rum/defc blocks-cp < rum/reactive db-mixins/query
|
||||
{}
|
||||
[repo page _format]
|
||||
[repo page]
|
||||
(when-let [page-e (db/pull [:block/name (util/page-name-sanity-lc page)])]
|
||||
(page/page-blocks-cp repo page-e {})))
|
||||
|
||||
(rum/defc journal-cp < rum/reactive
|
||||
[[title format]]
|
||||
[title]
|
||||
(let [;; Don't edit the journal title
|
||||
page (string/lower-case title)
|
||||
repo (state/sub :git/current-repo)
|
||||
@@ -56,9 +56,9 @@
|
||||
(gp-util/capitalize-all title)]]
|
||||
|
||||
(if today?
|
||||
(blocks-cp repo page format)
|
||||
(blocks-cp repo page)
|
||||
(ui/lazy-visible
|
||||
(fn [] (blocks-cp repo page format))
|
||||
(fn [] (blocks-cp repo page))
|
||||
{:debug-id (str "journal-blocks " page)}))
|
||||
|
||||
{})
|
||||
@@ -77,9 +77,9 @@
|
||||
[:div#journals
|
||||
(ui/infinite-list
|
||||
"main-content-container"
|
||||
(for [{:block/keys [name format]} latest-journals]
|
||||
(for [{:block/keys [name]} latest-journals]
|
||||
[:div.journal-item.content {:key name}
|
||||
(journal-cp [name format])])
|
||||
(journal-cp name)])
|
||||
{:has-more (page-handler/has-more-journals?)
|
||||
:more-class "text-4xl"
|
||||
:on-top-reached page-handler/create-today-journal!
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
:init-collapsed (fn [collapsed-atom]
|
||||
(reset! *collapsed? collapsed-atom))})))
|
||||
|
||||
(rum/defcs references* < rum/reactive
|
||||
(rum/defcs references* < rum/reactive db-mixins/query
|
||||
{:init (fn [state]
|
||||
(let [page-name (first (:rum/args state))
|
||||
filters (when page-name
|
||||
|
||||
@@ -378,6 +378,15 @@
|
||||
(get-file-path repo
|
||||
(str app-name "/" export-css-file)))))
|
||||
|
||||
(defn expand-relative-assets-path
|
||||
;; ../assets/xxx -> {assets|file}://{current-graph-root-path}/xxx
|
||||
[source]
|
||||
(when-let [protocol (and (string? source)
|
||||
(not (string/blank? source))
|
||||
(if (util/electron?) "assets" "file"))]
|
||||
|
||||
(string/replace
|
||||
source "../assets" (util/format "%s://%s/assets" protocol (get-repo-dir (state/get-current-repo))))))
|
||||
|
||||
(defn get-custom-js-path
|
||||
([]
|
||||
|
||||
@@ -356,28 +356,36 @@
|
||||
([blocks parent]
|
||||
(sort-by-left blocks parent {:check? true}))
|
||||
([blocks parent {:keys [check?]}]
|
||||
(when check?
|
||||
(when (not= (count blocks) (count (set (map :block/left blocks))))
|
||||
(let [duplicates (->> (map (comp :db/id :block/left) blocks)
|
||||
frequencies
|
||||
(filter (fn [[_k v]] (> v 1)))
|
||||
(map (fn [[k _v]]
|
||||
(let [left (db-utils/pull k)]
|
||||
{:left left
|
||||
:duplicates (->>
|
||||
(filter (fn [block]
|
||||
(= k (:db/id (:block/left block))))
|
||||
blocks)
|
||||
(map #(select-keys % [:db/id :block/level :block/content :block/file])))}))))]
|
||||
#_(util/pprint duplicates)))
|
||||
(assert (= (count blocks) (count (set (map :block/left blocks)))) "Each block should have a different left node"))
|
||||
(let [blocks (util/distinct-by :db/id blocks)]
|
||||
(when check?
|
||||
(when (not= (count blocks) (count (set (map :block/left blocks))))
|
||||
(let [duplicates (->> (map (comp :db/id :block/left) blocks)
|
||||
frequencies
|
||||
(filter (fn [[_k v]] (> v 1)))
|
||||
(map (fn [[k _v]]
|
||||
(let [left (db-utils/pull k)]
|
||||
{:left left
|
||||
:duplicates (->>
|
||||
(filter (fn [block]
|
||||
(= k (:db/id (:block/left block))))
|
||||
blocks)
|
||||
(map #(select-keys % [:db/id :block/level :block/content :block/file])))}))))]
|
||||
(util/pprint duplicates)))
|
||||
(assert (= (count blocks) (count (set (map :block/left blocks)))) "Each block should have a different left node"))
|
||||
|
||||
(let [left->blocks (reduce (fn [acc b] (assoc acc (:db/id (:block/left b)) b)) {} blocks)]
|
||||
(loop [block parent
|
||||
result []]
|
||||
(if-let [next (get left->blocks (:db/id block))]
|
||||
(recur next (conj result next))
|
||||
(vec result))))))
|
||||
(let [left->blocks (reduce (fn [acc b] (assoc acc (:db/id (:block/left b)) b)) {} blocks)]
|
||||
(loop [block parent
|
||||
result []]
|
||||
(if-let [next (get left->blocks (:db/id block))]
|
||||
(recur next (conj result next))
|
||||
(vec result)))))))
|
||||
|
||||
(defn try-sort-by-left
|
||||
[blocks parent]
|
||||
(let [result' (sort-by-left blocks parent {:check? false})]
|
||||
(if (= (count result') (count blocks))
|
||||
result'
|
||||
blocks)))
|
||||
|
||||
(defn sort-by-left-recursive
|
||||
[form]
|
||||
@@ -450,6 +458,11 @@
|
||||
parent-sibling
|
||||
(get-next-outdented-block db (:db/id parent))))))
|
||||
|
||||
(defn top-block?
|
||||
[block]
|
||||
(= (:db/id (:block/parent block))
|
||||
(:db/id (:block/page block))))
|
||||
|
||||
(defn get-block-parent
|
||||
([block-id]
|
||||
(get-block-parent (state/get-current-repo) block-id))
|
||||
@@ -458,11 +471,6 @@
|
||||
(when-let [block (d/entity db [:block/uuid block-id])]
|
||||
(:block/parent block)))))
|
||||
|
||||
(defn top-block?
|
||||
[block]
|
||||
(= (:db/id (:block/parent block))
|
||||
(:db/id (:block/page block))))
|
||||
|
||||
;; non recursive query
|
||||
(defn get-block-parents
|
||||
([repo block-id]
|
||||
@@ -477,13 +485,6 @@
|
||||
(recur (:block/uuid parent) (conj parents parent) (inc d))
|
||||
parents)))))
|
||||
|
||||
(comment
|
||||
(defn get-immediate-children-v2
|
||||
[repo block-id]
|
||||
(d/pull (conn/get-db repo)
|
||||
'[:block/_parent]
|
||||
[:block/uuid block-id])))
|
||||
|
||||
;; Use built-in recursive
|
||||
(defn get-block-parents-v2
|
||||
[repo block-id]
|
||||
@@ -859,17 +860,14 @@
|
||||
(defn get-block-children-ids
|
||||
[repo block-uuid]
|
||||
(when-let [db (conn/get-db repo)]
|
||||
(let [eid (:db/id (db-utils/entity repo [:block/uuid block-uuid]))]
|
||||
(->> (d/q
|
||||
'[:find ?id
|
||||
:in $ ?p %
|
||||
:where
|
||||
(child ?p ?c)
|
||||
[?c :block/uuid ?id]]
|
||||
db
|
||||
eid
|
||||
rules)
|
||||
(apply concat)))))
|
||||
(when-let [eid (:db/id (db-utils/entity repo [:block/uuid block-uuid]))]
|
||||
(let [get-children-ids (fn get-children-ids [eid]
|
||||
(mapcat
|
||||
(fn [datom]
|
||||
(let [id (first datom)]
|
||||
(cons (:block/uuid (d/entity db id)) (get-children-ids id))))
|
||||
(d/datoms db :avet :block/parent eid)))]
|
||||
(get-children-ids eid)))))
|
||||
|
||||
(defn get-block-immediate-children
|
||||
"Doesn't include nested children."
|
||||
@@ -1173,21 +1171,19 @@
|
||||
(get-page-referenced-blocks-full (state/get-current-repo) page options))
|
||||
([repo page options]
|
||||
(when repo
|
||||
(when (conn/get-db repo)
|
||||
(when-let [db (conn/get-db repo)]
|
||||
(let [page-id (:db/id (db-utils/entity [:block/name (util/safe-page-name-sanity-lc page)]))
|
||||
pages (page-alias-set repo page)
|
||||
aliases (set/difference pages #{page-id})]
|
||||
(->>
|
||||
(react/q repo
|
||||
[:frontend.db.react/page<-blocks-or-block<-blocks page-id]
|
||||
{}
|
||||
'[:find [(pull ?block ?block-attrs) ...]
|
||||
:in $ [?ref-page ...] ?block-attrs
|
||||
:where
|
||||
[?block :block/path-refs ?ref-page]]
|
||||
pages
|
||||
(butlast block-attrs))
|
||||
react
|
||||
(d/q
|
||||
'[:find [(pull ?block ?block-attrs) ...]
|
||||
:in $ [?ref-page ...] ?block-attrs
|
||||
:where
|
||||
[?block :block/path-refs ?ref-page]]
|
||||
db
|
||||
pages
|
||||
(butlast block-attrs))
|
||||
(remove (fn [block] (= page-id (:db/id (:block/page block)))))
|
||||
db-utils/group-by-page
|
||||
(map (fn [[k blocks]]
|
||||
@@ -1209,17 +1205,16 @@
|
||||
aliases (set/difference pages #{page-id})]
|
||||
(->>
|
||||
(react/q repo
|
||||
[:frontend.db.react/page<-blocks-or-block<-blocks page-id]
|
||||
{:use-cache? false
|
||||
:query-fn (fn []
|
||||
(let [entities (mapcat (fn [id]
|
||||
(:block/_path-refs (db-utils/entity id))) pages)
|
||||
blocks (map (fn [e] {:block/parent (:block/parent e)
|
||||
:block/left (:block/left e)
|
||||
:block/page (:block/page e)}) entities)]
|
||||
{:entities entities
|
||||
:blocks blocks}))}
|
||||
nil)
|
||||
[:frontend.db.react/refs page-id]
|
||||
{:query-fn (fn []
|
||||
(let [entities (mapcat (fn [id]
|
||||
(:block/_path-refs (db-utils/entity id))) pages)
|
||||
blocks (map (fn [e] {:block/parent (:block/parent e)
|
||||
:block/left (:block/left e)
|
||||
:block/page (:block/page e)}) entities)]
|
||||
{:entities entities
|
||||
:blocks blocks}))}
|
||||
nil)
|
||||
react
|
||||
:entities
|
||||
(remove (fn [block] (= page-id (:db/id (:block/page block)))))
|
||||
@@ -1239,16 +1234,15 @@
|
||||
page? (:block/name block)
|
||||
result (if page?
|
||||
(let [pages (page-alias-set repo (:block/name block))]
|
||||
(d/q
|
||||
'[:find [?block ...]
|
||||
:in $ [?ref-page ...] ?id
|
||||
:where
|
||||
[?block :block/refs ?ref-page]
|
||||
[?block :block/page ?p]
|
||||
[(not= ?p ?id)]]
|
||||
(conn/get-db repo)
|
||||
pages
|
||||
id))
|
||||
@(react/q repo [:frontend.db.react/refs-count id] {}
|
||||
'[:find [?block ...]
|
||||
:in $ [?ref-page ...] ?id
|
||||
:where
|
||||
[?block :block/refs ?ref-page]
|
||||
[?block :block/page ?p]
|
||||
[(not= ?p ?id)]]
|
||||
pages
|
||||
id))
|
||||
(:block/_refs block))]
|
||||
(count result))))
|
||||
|
||||
@@ -1312,8 +1306,6 @@
|
||||
(sort-by-left-recursive)
|
||||
db-utils/group-by-page)))))
|
||||
|
||||
;; TODO: Replace recursive queries with datoms index implementation
|
||||
;; see https://github.com/tonsky/datascript/issues/130#issuecomment-169520434
|
||||
(defn get-block-referenced-blocks
|
||||
([block-uuid]
|
||||
(get-block-referenced-blocks block-uuid {}))
|
||||
@@ -1321,16 +1313,16 @@
|
||||
(when-let [repo (state/get-current-repo)]
|
||||
(when (conn/get-db repo)
|
||||
(let [block (db-utils/entity [:block/uuid block-uuid])
|
||||
query-result (->> (react/q repo [:frontend.db.react/page<-blocks-or-block<-blocks
|
||||
query-result (->> (react/q repo [:frontend.db.react/refs
|
||||
(:db/id block)]
|
||||
{:use-cache? false}
|
||||
'[:find [(pull ?ref-block ?block-attrs) ...]
|
||||
:in $ ?block-uuid ?block-attrs
|
||||
:where
|
||||
[?block :block/uuid ?block-uuid]
|
||||
[?ref-block :block/refs ?block]]
|
||||
block-uuid
|
||||
block-attrs)
|
||||
{}
|
||||
'[:find [(pull ?ref-block ?block-attrs) ...]
|
||||
:in $ ?block-uuid ?block-attrs
|
||||
:where
|
||||
[?block :block/uuid ?block-uuid]
|
||||
[?ref-block :block/refs ?block]]
|
||||
block-uuid
|
||||
block-attrs)
|
||||
react
|
||||
(sort-by-left-recursive))]
|
||||
(db-utils/group-by-page query-result))))))
|
||||
|
||||
@@ -24,38 +24,29 @@
|
||||
;; get block&children react-query
|
||||
(s/def ::block-and-children (s/tuple #(= ::block-and-children %) uuid?))
|
||||
|
||||
(s/def ::block-direct-children (s/tuple #(= ::block-direct-children %) uuid?))
|
||||
;; ::journals
|
||||
;; get journal-list react-query
|
||||
(s/def ::journals (s/tuple #(= ::journals %)))
|
||||
;; ::page->pages
|
||||
;; get PAGES referenced by PAGE
|
||||
(s/def ::page->pages (s/tuple #(= ::page->pages %) int?))
|
||||
;; ::page<-pages
|
||||
;; get PAGES referencing PAGE
|
||||
(s/def ::page<-pages (s/tuple #(= ::page<-pages %) int?))
|
||||
;; ::page<-blocks-or-block<-blocks
|
||||
;; ::refs
|
||||
;; get BLOCKS referencing PAGE or BLOCK
|
||||
(s/def ::page<-blocks-or-block<-blocks
|
||||
(s/tuple #(= ::page<-blocks-or-block<-blocks %) int?))
|
||||
;; FIXME: this react-query has performance issues
|
||||
(s/def ::page-unlinked-refs (s/tuple #(= ::page-unlinked-refs %) int?))
|
||||
;; ::block<-block-ids
|
||||
;; get BLOCK-IDS referencing BLOCK
|
||||
(s/def ::block<-block-ids (s/tuple #(= ::block<-block-ids %) int?))
|
||||
(s/def ::refs (s/tuple #(= ::refs %) int?))
|
||||
;; ::refs-count
|
||||
;; get refs count
|
||||
(s/def ::refs-count int?)
|
||||
|
||||
;; custom react-query
|
||||
(s/def ::custom any?)
|
||||
|
||||
(s/def ::react-query-keys (s/or :block ::block
|
||||
:page-blocks ::page-blocks
|
||||
:block-and-children ::block-and-children
|
||||
:block-direct-children ::block-direct-children
|
||||
:journals ::journals
|
||||
:page->pages ::page->pages
|
||||
:page<-pages ::page<-pages
|
||||
:page<-blocks-or-block<-blocks ::page<-blocks-or-block<-blocks
|
||||
:page-unlinked-refs ::page-unlinked-refs
|
||||
:block<-block-ids ::block<-block-ids
|
||||
:refs ::refs
|
||||
:refs-count ::refs-count
|
||||
:custom ::custom))
|
||||
|
||||
(s/def ::affected-keys (s/coll-of ::react-query-keys))
|
||||
@@ -125,13 +116,14 @@
|
||||
|
||||
(defn add-q!
|
||||
[k query time inputs result-atom transform-fn query-fn inputs-fn]
|
||||
(swap! query-state assoc k {:query query
|
||||
:query-time time
|
||||
:inputs inputs
|
||||
:result result-atom
|
||||
:transform-fn transform-fn
|
||||
:query-fn query-fn
|
||||
:inputs-fn inputs-fn})
|
||||
(let [time' (int (util/safe-parse-float time))]
|
||||
(swap! query-state assoc k {:query query
|
||||
:query-time time'
|
||||
:inputs inputs
|
||||
:result result-atom
|
||||
:transform-fn transform-fn
|
||||
:query-fn query-fn
|
||||
:inputs-fn inputs-fn}))
|
||||
result-atom)
|
||||
|
||||
(defn remove-q!
|
||||
@@ -141,14 +133,16 @@
|
||||
(defn add-query-component!
|
||||
[key component]
|
||||
(when (and key component)
|
||||
(swap! query-components assoc component key)))
|
||||
(swap! query-components update component (fn [col] (set (conj col key))))))
|
||||
|
||||
(defn remove-query-component!
|
||||
[component]
|
||||
(when-let [query (get @query-components component)]
|
||||
(let [matched-queries (filter #(= query %) (vals @query-components))]
|
||||
(when (= 1 (count matched-queries))
|
||||
(remove-q! query))))
|
||||
(when-let [queries (get @query-components component)]
|
||||
(let [all-queries (apply concat (vals @query-components))]
|
||||
(doseq [query queries]
|
||||
(let [matched-queries (filter #(= query %) all-queries)]
|
||||
(when (= 1 (count matched-queries))
|
||||
(remove-q! query))))))
|
||||
(swap! query-components dissoc component))
|
||||
|
||||
;; TODO: rename :custom to :query/custom
|
||||
@@ -220,64 +214,80 @@
|
||||
(let [page-name (util/page-name-sanity-lc page)]
|
||||
(db-utils/entity [:block/name page-name])))))
|
||||
|
||||
(defn- get-block-parents
|
||||
[db id]
|
||||
(let [get-parent (fn [id] (:db/id (:block/parent (d/entity db id))))]
|
||||
(loop [result [id]
|
||||
id id]
|
||||
(if-let [parent (get-parent id)]
|
||||
(recur (conj result parent) parent)
|
||||
result))))
|
||||
|
||||
(defn- get-blocks-parents-from-both-dbs
|
||||
[db-after db-before block-entities]
|
||||
(let [current-db-parent-ids (->> (set (keep :block/parent block-entities))
|
||||
(mapcat (fn [parent]
|
||||
(get-block-parents db-after (:db/id parent)))))
|
||||
before-db-parent-ids (->> (map :db/id block-entities)
|
||||
(mapcat (fn [id]
|
||||
(get-block-parents db-before id))))]
|
||||
(set (concat current-db-parent-ids before-db-parent-ids))))
|
||||
|
||||
(defn get-affected-queries-keys
|
||||
"Get affected queries through transaction datoms."
|
||||
[{:keys [tx-data db-before]}]
|
||||
[{:keys [tx-data db-before db-after]}]
|
||||
{:post [(s/valid? ::affected-keys %)]}
|
||||
(let [blocks (->> (filter (fn [datom] (contains? #{:block/left :block/parent :block/page} (:a datom))) tx-data)
|
||||
(map :v)
|
||||
(distinct))
|
||||
refs (->> (filter (fn [datom] (= :block/refs (:a datom))) tx-data)
|
||||
refs (->> (filter (fn [datom] (contains? #{:block/refs :block/path-refs} (:a datom))) tx-data)
|
||||
(map :v)
|
||||
(distinct))
|
||||
other-blocks (->> (filter (fn [datom] (= "block" (namespace (:a datom)))) tx-data)
|
||||
(map :e))
|
||||
blocks (-> (concat blocks other-blocks) distinct)
|
||||
block-entities (keep (fn [block-id]
|
||||
(let [block-id (if (and (string? block-id) (util/uuid-string? block-id))
|
||||
[:block/uuid block-id]
|
||||
block-id)]
|
||||
(db-utils/entity block-id))) blocks)
|
||||
affected-keys (concat
|
||||
(mapcat
|
||||
(fn [block-id]
|
||||
(let [block-id (if (and (string? block-id) (util/uuid-string? block-id))
|
||||
[:block/uuid block-id]
|
||||
block-id)]
|
||||
(when-let [block (db-utils/entity block-id)]
|
||||
(let [page-id (or
|
||||
(when (:block/name block) (:db/id block))
|
||||
(:db/id (:block/page block)))
|
||||
blocks [[::block (:db/id block)]]
|
||||
others (when page-id
|
||||
(let [db-after-parent-uuid (:block/uuid (:block/parent block))
|
||||
db-before-parent-uuid (:block/uuid (:block/parent (d/entity db-before
|
||||
[:block/uuid (:block/uuid block)])))]
|
||||
[[::page-blocks page-id]
|
||||
[::page->pages page-id]
|
||||
[::block-direct-children db-after-parent-uuid]
|
||||
(when (and db-before-parent-uuid
|
||||
(not= db-before-parent-uuid db-after-parent-uuid))
|
||||
[::block-direct-children db-before-parent-uuid])]))]
|
||||
(concat blocks others)))))
|
||||
blocks)
|
||||
(fn [block]
|
||||
(let [page-id (or
|
||||
(when (:block/name block) (:db/id block))
|
||||
(:db/id (:block/page block)))
|
||||
blocks [[::block (:db/id block)]]
|
||||
path-refs (:block/path-refs block)
|
||||
path-refs' (mapcat (fn [ref]
|
||||
[
|
||||
;; [::refs-count (:db/id ref)]
|
||||
[::refs (:db/id ref)]]) path-refs)
|
||||
page-blocks (when page-id
|
||||
[[::page-blocks page-id]])]
|
||||
(concat blocks page-blocks path-refs')))
|
||||
block-entities)
|
||||
|
||||
(mapcat
|
||||
(fn [ref]
|
||||
[
|
||||
;; [::refs-count (:db/id entity)]
|
||||
[::refs ref]])
|
||||
refs)
|
||||
|
||||
(when-let [current-page-id (:db/id (get-current-page))]
|
||||
[[::page->pages current-page-id]
|
||||
[::page<-pages current-page-id]])
|
||||
|
||||
(map (fn [ref]
|
||||
(let [entity (db-utils/entity ref)]
|
||||
(if (:block/name entity) ; page
|
||||
[::page-blocks ref]
|
||||
[::page-blocks (:db/id (:block/page entity))])))
|
||||
refs))
|
||||
others (->>
|
||||
(keys @query-state)
|
||||
(filter (fn [ks]
|
||||
(contains? #{::block-and-children
|
||||
::page<-blocks-or-block<-blocks}
|
||||
(second ks))))
|
||||
(map (fn [v] (vec (rest v)))))]
|
||||
[[::page<-pages current-page-id]]))
|
||||
parent-ids (get-blocks-parents-from-both-dbs db-after db-before block-entities)
|
||||
block-children-keys (->>
|
||||
(keys @query-state)
|
||||
(keep (fn [ks]
|
||||
(when (and (= ::block-and-children (second ks))
|
||||
(contains? parent-ids (last ks)))
|
||||
(vec (rest ks))))))]
|
||||
(->>
|
||||
(util/concat-without-nil
|
||||
affected-keys
|
||||
others)
|
||||
block-children-keys)
|
||||
set)))
|
||||
|
||||
(defn- execute-query!
|
||||
@@ -314,8 +324,6 @@
|
||||
(when-let [outliner-op (:outliner-op tx-meta)]
|
||||
(not (or
|
||||
(contains? #{:collapse-expand-blocks :delete-blocks} outliner-op)
|
||||
;; ignore move up/down since it doesn't affect the refs for any blocks
|
||||
(contains? #{:move-blocks-up-down} (:move-op tx-meta))
|
||||
(:undo? tx-meta) (:redo? tx-meta)))))
|
||||
|
||||
(defn refresh!
|
||||
@@ -335,16 +343,18 @@
|
||||
custom?
|
||||
kv?))
|
||||
(let [{:keys [query query-fn]} cache
|
||||
query-or-refs? (state/edit-in-query-or-refs-component)]
|
||||
(when (or query query-fn)
|
||||
(try
|
||||
(let [f #(execute-query! repo-url db k tx cache {:skip-query-time-check? query-or-refs?})]
|
||||
;; Detects whether user is editing in a custom query, if so, execute the query immediately
|
||||
(if (or query-or-refs? (not custom?))
|
||||
(f)
|
||||
(async/put! (state/get-reactive-custom-queries-chan) [f query])))
|
||||
(catch js/Error e
|
||||
(js/console.error e))))))))))))
|
||||
{:keys [custom-query?]} (state/edit-in-query-or-refs-component)]
|
||||
(util/profile
|
||||
(str "refresh! " (rest k))
|
||||
(when (or query query-fn)
|
||||
(try
|
||||
(let [f #(execute-query! repo-url db k tx cache {:skip-query-time-check? custom-query?})]
|
||||
;; Detects whether user is editing in a custom query, if so, execute the query immediately
|
||||
(if (and custom? (not custom-query?))
|
||||
(async/put! (state/get-reactive-custom-queries-chan) [f query])
|
||||
(f)))
|
||||
(catch js/Error e
|
||||
(js/console.error e)))))))))))))
|
||||
|
||||
(defn set-key-value
|
||||
[repo-url key value]
|
||||
|
||||
@@ -205,8 +205,8 @@
|
||||
|
||||
(defn clear-selection!
|
||||
[]
|
||||
(util/select-unhighlight! (dom/by-class "selected"))
|
||||
(state/clear-selection!))
|
||||
(state/clear-selection!)
|
||||
(util/select-unhighlight! (dom/by-class "selected")))
|
||||
|
||||
(defn- text-range-by-lst-fst-line [content [direction pos]]
|
||||
(case direction
|
||||
@@ -1073,8 +1073,11 @@
|
||||
(when-let [blocks (seq (get-selected-blocks))]
|
||||
;; remove embeds, references and queries
|
||||
(let [dom-blocks (remove (fn [block]
|
||||
(or (= "true" (dom/attr block "data-transclude"))
|
||||
(= "true" (dom/attr block "data-query")))) blocks)]
|
||||
(or (= "true" (dom/attr block "data-transclude"))
|
||||
(= "true" (dom/attr block "data-query")))) blocks)
|
||||
dom-blocks (if (seq dom-blocks) dom-blocks
|
||||
(remove (fn [block]
|
||||
(= "true" (dom/attr block "data-transclude"))) blocks))]
|
||||
(when (seq dom-blocks)
|
||||
(let [repo (state/get-current-repo)
|
||||
block-uuids (distinct (map #(uuid (dom/attr % "blockid")) dom-blocks))
|
||||
@@ -1220,8 +1223,7 @@
|
||||
|
||||
(defn clear-last-selected-block!
|
||||
[]
|
||||
(let [block (state/drop-last-selection-block!)]
|
||||
(util/select-unhighlight! [block])))
|
||||
(state/drop-last-selection-block!))
|
||||
|
||||
(defn highlight-selection-area!
|
||||
[end-block]
|
||||
@@ -1236,18 +1238,18 @@
|
||||
(defn- select-block-up-down
|
||||
[direction]
|
||||
(cond
|
||||
;; when editing, quit editing and select current block
|
||||
;; when editing, quit editing and select current block
|
||||
(state/editing?)
|
||||
(state/exit-editing-and-set-selected-blocks! [(gdom/getElement (state/get-editing-block-dom-id))])
|
||||
|
||||
;; when selection and one block selected, select next block
|
||||
;; when selection and one block selected, select next block
|
||||
(and (state/selection?) (== 1 (count (state/get-selection-blocks))))
|
||||
(let [f (if (= :up direction) util/get-prev-block-non-collapsed util/get-next-block-non-collapsed-skip)
|
||||
element (f (first (state/get-selection-blocks)))]
|
||||
(when element
|
||||
(state/conj-selection-block! element direction)))
|
||||
|
||||
;; if same direction, keep conj on same direction
|
||||
;; if same direction, keep conj on same direction
|
||||
(and (state/selection?) (= direction (state/get-selection-direction)))
|
||||
(let [f (if (= :up direction) util/get-prev-block-non-collapsed util/get-next-block-non-collapsed-skip)
|
||||
first-last (if (= :up direction) first last)
|
||||
@@ -1255,7 +1257,7 @@
|
||||
(when element
|
||||
(state/conj-selection-block! element direction)))
|
||||
|
||||
;; if different direction, keep clear until one left
|
||||
;; if different direction, keep clear until one left
|
||||
(state/selection?)
|
||||
(clear-last-selected-block!))
|
||||
nil)
|
||||
@@ -1734,6 +1736,13 @@
|
||||
:markdown (util/format "" label link)
|
||||
:org (util/format "[[%s]]"))))
|
||||
|
||||
(defn handle-command-input-close [id]
|
||||
(state/set-editor-show-input! nil)
|
||||
(when-let [saved-cursor (state/get-editor-last-pos)]
|
||||
(when-let [input (gdom/getElement id)]
|
||||
(.focus input)
|
||||
(cursor/move-cursor-to input saved-cursor))))
|
||||
|
||||
(defn handle-command-input [command id format m]
|
||||
;; TODO: Add error handling for when user doesn't provide a required field.
|
||||
;; (The current behavior is to just revert back to the editor.)
|
||||
@@ -1757,41 +1766,24 @@
|
||||
|
||||
nil)
|
||||
|
||||
(state/set-editor-show-input! nil)
|
||||
|
||||
(when-let [saved-cursor (state/get-editor-last-pos)]
|
||||
(when-let [input (gdom/getElement id)]
|
||||
(.focus input)
|
||||
(cursor/move-cursor-to input saved-cursor))))
|
||||
|
||||
(defn get-search-q
|
||||
[]
|
||||
(when-let [id (state/get-edit-input-id)]
|
||||
(when-let [input (gdom/getElement id)]
|
||||
(let [current-pos (cursor/pos input)
|
||||
pos (state/get-editor-last-pos)
|
||||
edit-content (or (state/sub [:editor/content id]) "")]
|
||||
(or
|
||||
@*selected-text
|
||||
(gp-util/safe-subs edit-content pos current-pos))))))
|
||||
(handle-command-input-close id))
|
||||
|
||||
(defn close-autocomplete-if-outside
|
||||
[input]
|
||||
(when (and input
|
||||
(state/get-editor-action)
|
||||
(not (wrapped-by? input page-ref/left-brackets page-ref/right-brackets)))
|
||||
(when (get-search-q)
|
||||
(let [value (gobj/get input "value")
|
||||
pos (state/get-editor-last-pos)
|
||||
current-pos (cursor/pos input)
|
||||
between (gp-util/safe-subs value (min pos current-pos) (max pos current-pos))]
|
||||
(when (and between
|
||||
(or
|
||||
(string/includes? between "[")
|
||||
(string/includes? between "]")
|
||||
(string/includes? between "(")
|
||||
(string/includes? between ")")))
|
||||
(state/clear-editor-action!))))))
|
||||
(let [value (gobj/get input "value")
|
||||
pos (state/get-editor-last-pos)
|
||||
current-pos (cursor/pos input)
|
||||
between (gp-util/safe-subs value (min pos current-pos) (max pos current-pos))]
|
||||
(when (and between
|
||||
(or
|
||||
(string/includes? between "[")
|
||||
(string/includes? between "]")
|
||||
(string/includes? between "(")
|
||||
(string/includes? between ")")))
|
||||
(state/clear-editor-action!)))))
|
||||
|
||||
(defn resize-image!
|
||||
[block-id metadata full_text size]
|
||||
@@ -1821,7 +1813,7 @@
|
||||
(reset! *auto-save-timeout
|
||||
(js/setTimeout
|
||||
(fn []
|
||||
(when (state/input-idle? repo)
|
||||
(when (state/input-idle? repo :diff 500)
|
||||
(state/set-editor-op! :auto-save)
|
||||
; don't auto-save for page's properties block
|
||||
(save-current-block! {:skip-properties? true})
|
||||
@@ -2816,7 +2808,7 @@
|
||||
nil))))
|
||||
|
||||
(defn ^:large-vars/cleanup-todo keyup-handler
|
||||
[_state input input-id search-timeout]
|
||||
[_state input input-id]
|
||||
(fn [e key-code]
|
||||
(when-not (util/event-is-composing? e)
|
||||
(let [current-pos (cursor/pos input)
|
||||
@@ -2889,7 +2881,7 @@
|
||||
(when (and (not editor-action) (not non-enter-processed?))
|
||||
(cond
|
||||
;; When you type text inside square brackets
|
||||
(and (not (contains? #{"ArrowDown" "ArrowLeft" "ArrowRight" "ArrowUp"} k))
|
||||
(and (not (contains? #{"ArrowDown" "ArrowLeft" "ArrowRight" "ArrowUp" "Escape"} k))
|
||||
(wrapped-by? input page-ref/left-brackets page-ref/right-brackets))
|
||||
(let [orig-pos (cursor/get-caret-pos input)
|
||||
value (gobj/get input "value")
|
||||
@@ -2937,11 +2929,11 @@
|
||||
(state/set-editor-action-data! {:pos (cursor/get-caret-pos input)})
|
||||
(state/set-editor-show-block-commands!))
|
||||
|
||||
(nil? @search-timeout)
|
||||
(close-autocomplete-if-outside input)
|
||||
|
||||
:else
|
||||
nil)))
|
||||
|
||||
(close-autocomplete-if-outside input)
|
||||
|
||||
(when-not (or (= k "Shift") is-processed?)
|
||||
(state/set-last-key-code! {:key-code key-code
|
||||
:code code
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns frontend.handler.editor.keyboards
|
||||
(:require [dommy.core :as d]
|
||||
[frontend.handler.editor :as editor-handler]
|
||||
(:require [frontend.handler.editor :as editor-handler]
|
||||
[frontend.mixins :as mixins]
|
||||
[frontend.state :as state]
|
||||
[goog.dom :as gdom]))
|
||||
@@ -12,15 +11,26 @@
|
||||
(mixins/hide-when-esc-or-outside
|
||||
state
|
||||
:on-hide
|
||||
(fn [_state e event]
|
||||
(let [target (.-target e)]
|
||||
(if (d/has-class? target "bottom-action") ;; FIXME: not particular case
|
||||
(.preventDefault e)
|
||||
(let [{:keys [on-hide value]} (editor-handler/get-state)]
|
||||
(when on-hide
|
||||
(on-hide value event))
|
||||
(when (contains? #{:esc :visibilitychange :click} event)
|
||||
(state/clear-edit!))))))
|
||||
(fn [_state _e event]
|
||||
(cond
|
||||
(contains?
|
||||
#{:commands :block-commands
|
||||
:page-search :page-search-hashtag :block-search :template-search
|
||||
:property-search :property-value-search
|
||||
:datepicker}
|
||||
(state/get-editor-action))
|
||||
(state/clear-editor-action!) ;; FIXME: This should probably be handled as a keydown handler in editor, but this handler intercepts Esc first
|
||||
|
||||
;; editor/input component handles Escape directly, so just prevent handling it here
|
||||
(= :input (state/get-editor-action))
|
||||
nil
|
||||
|
||||
:else
|
||||
(let [{:keys [on-hide value]} (editor-handler/get-state)]
|
||||
(when on-hide
|
||||
(on-hide value event))
|
||||
(when (contains? #{:esc :visibilitychange :click} event)
|
||||
(state/clear-edit!)))))
|
||||
:node (gdom/getElement id)
|
||||
;; :visibilitychange? true
|
||||
)))
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
[e]
|
||||
(util/stop e)
|
||||
(state/set-editor-op! :undo)
|
||||
(state/clear-editor-action!)
|
||||
(editor/save-current-block!)
|
||||
(let [{:keys [editor-cursor]} (undo-redo/undo)]
|
||||
(restore-cursor! editor-cursor))
|
||||
@@ -30,6 +31,7 @@
|
||||
[e]
|
||||
(util/stop e)
|
||||
(state/set-editor-op! :redo)
|
||||
(state/clear-editor-action!)
|
||||
(let [{:keys [editor-cursor]} (undo-redo/redo)]
|
||||
(restore-cursor! editor-cursor))
|
||||
(state/set-editor-op! nil))
|
||||
|
||||
@@ -125,7 +125,8 @@
|
||||
[]
|
||||
(when-let [style (or
|
||||
(state/get-custom-css-link)
|
||||
(db-model/get-custom-css)
|
||||
(some-> (db-model/get-custom-css)
|
||||
(config/expand-relative-assets-path))
|
||||
;; (state/get-custom-css-link)
|
||||
)]
|
||||
(util/add-style! style)))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns frontend.mixins
|
||||
(:require [rum.core :as rum]
|
||||
[goog.dom :as dom]
|
||||
[frontend.util :refer [profile]]
|
||||
[frontend.util :refer [profile] :as util]
|
||||
[frontend.state :as state])
|
||||
(:import [goog.events EventHandler]))
|
||||
|
||||
@@ -26,43 +26,21 @@
|
||||
(detach state)
|
||||
(dissoc state ::event-handler))})
|
||||
|
||||
;; (defn timeout-mixin
|
||||
;; "The setTimeout mixin."
|
||||
;; [name t f]
|
||||
;; {:will-mount
|
||||
;; (fn [state]
|
||||
;; (assoc state name (util/set-timeout t f)))
|
||||
;; :will-unmount
|
||||
;; (fn [state]
|
||||
;; (let [timeout (get state name)]
|
||||
;; (util/clear-timeout timeout)
|
||||
;; (dissoc state name)))})
|
||||
|
||||
;; (defn interval-mixin
|
||||
;; "The setInterval mixin."
|
||||
;; [name t f]
|
||||
;; {:will-mount
|
||||
;; (fn [state]
|
||||
;; (assoc state name (util/set-interval t f)))
|
||||
;; :will-unmount
|
||||
;; (fn [state]
|
||||
;; (when-let [interval (get state name)]
|
||||
;; (util/clear-interval interval))
|
||||
;; (dissoc state name))})
|
||||
|
||||
(defn hide-when-esc-or-outside
|
||||
[state & {:keys [on-hide node visibilitychange? outside?]}]
|
||||
(try
|
||||
(let [dom-node (rum/dom-node state)]
|
||||
(when-let [dom-node (or node dom-node)]
|
||||
(or (false? outside?)
|
||||
(listen state js/window "mousedown"
|
||||
(fn [e]
|
||||
(let [target (.. e -target)]
|
||||
;; If the click target is outside of current node
|
||||
(when (and (not (dom/contains dom-node target))
|
||||
(not (.contains (.-classList target) "ignore-outside-event")))
|
||||
(on-hide state e :click))))))
|
||||
(let [click-fn (fn [e]
|
||||
(let [target (.. e -target)]
|
||||
;; If the click target is outside of current node
|
||||
(when (and
|
||||
(not (util/input? dom-node))
|
||||
(not (dom/contains dom-node target))
|
||||
(not (.contains (.-classList target) "ignore-outside-event")))
|
||||
(on-hide state e :click))))]
|
||||
(when-not (false? outside?)
|
||||
(listen state js/window "mouseup" click-fn)))
|
||||
(listen state js/window "keydown"
|
||||
(fn [e]
|
||||
(case (.-keyCode e)
|
||||
|
||||
@@ -46,18 +46,21 @@
|
||||
[repo page-db-id]
|
||||
(let [page-block (db/pull repo '[*] page-db-id)
|
||||
page-db-id (:db/id page-block)
|
||||
whiteboard? (:block/whiteboard? page-block)
|
||||
pull-keys (if whiteboard? whiteboard-blocks-pull-keys-with-persisted-ids '[*])
|
||||
blocks (model/get-page-blocks-no-cache repo (:block/name page-block) {:pull-keys pull-keys})
|
||||
blocks (if whiteboard? (map cleanup-whiteboard-block blocks) blocks)]
|
||||
|
||||
(when-not (and (= 1 (count blocks))
|
||||
(string/blank? (:block/content (first blocks)))
|
||||
(nil? (:block/file page-block)))
|
||||
(let [tree (tree/blocks->vec-tree repo blocks (:block/name page-block))]
|
||||
(if page-block
|
||||
(file/save-tree! page-block (if whiteboard? blocks tree))
|
||||
(js/console.error (str "can't find page id: " page-db-id)))))))
|
||||
blocks-count (model/get-page-blocks-count repo page-db-id)]
|
||||
(if (and (> blocks-count 500)
|
||||
(not (state/input-idle? repo :diff 3000))) ; long page
|
||||
(async/put! write-chan [repo page-db-id])
|
||||
(let [whiteboard? (:block/whiteboard? page-block)
|
||||
pull-keys (if whiteboard? whiteboard-blocks-pull-keys-with-persisted-ids '[*])
|
||||
blocks (model/get-page-blocks-no-cache repo (:block/name page-block) {:pull-keys pull-keys})
|
||||
blocks (if whiteboard? (map cleanup-whiteboard-block blocks) blocks)]
|
||||
(when-not (and (= 1 (count blocks))
|
||||
(string/blank? (:block/content (first blocks)))
|
||||
(nil? (:block/file page-block)))
|
||||
(let [tree (tree/blocks->vec-tree repo blocks (:block/name page-block))]
|
||||
(if page-block
|
||||
(file/save-tree! page-block (if whiteboard? blocks tree))
|
||||
(js/console.error (str "can't find page id: " page-db-id)))))))))
|
||||
|
||||
(defn write-files!
|
||||
[pages]
|
||||
|
||||
@@ -23,7 +23,10 @@
|
||||
(defn compute-block-path-refs
|
||||
[tx-meta blocks]
|
||||
(let [repo (state/get-current-repo)
|
||||
blocks (remove :block/name blocks)]
|
||||
blocks (remove :block/name blocks)
|
||||
blocks (if (= (:outliner-op tx-meta) :insert-blocks)
|
||||
(butlast blocks)
|
||||
blocks)]
|
||||
(when (:outliner-op tx-meta)
|
||||
(when (react/path-refs-need-recalculated? tx-meta)
|
||||
(let [*computed-ids (atom #{})]
|
||||
@@ -61,7 +64,9 @@
|
||||
(not (:compute-new-refs? tx-meta)))
|
||||
(let [{:keys [pages blocks]} (ds-report/get-blocks-and-pages tx-report)
|
||||
repo (state/get-current-repo)
|
||||
refs-tx (set (compute-block-path-refs (:tx-meta tx-report) blocks))
|
||||
refs-tx (util/profile
|
||||
"Compute path refs: "
|
||||
(set (compute-block-path-refs (:tx-meta tx-report) blocks)))
|
||||
truncate-refs-tx (map (fn [m] [:db/retract (:db/id m) :block/path-refs]) refs-tx)
|
||||
tx (util/concat-without-nil truncate-refs-tx refs-tx)
|
||||
tx-report' (if (seq tx)
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
root-block (assoc root-block :block/children result)]
|
||||
[root-block])))))))
|
||||
|
||||
(defn- tree [flat-nodes root-id]
|
||||
(let [children (group-by :block/parent flat-nodes)
|
||||
(defn- tree [parent->children root]
|
||||
(let [root-id (:db/id root)
|
||||
nodes (fn nodes [parent-id level]
|
||||
(mapv (fn [b]
|
||||
(let [b' (assoc b :block/level (inc level))
|
||||
@@ -75,8 +75,14 @@
|
||||
(if (seq children)
|
||||
(assoc b' :block/children children)
|
||||
b')))
|
||||
(get children {:db/id parent-id})))]
|
||||
(nodes root-id 1)))
|
||||
(let [parent {:db/id parent-id}]
|
||||
(-> (get parent->children parent)
|
||||
(model/try-sort-by-left parent)))))
|
||||
children (nodes root-id 1)
|
||||
root' (assoc root :block/level 1)]
|
||||
(if (seq children)
|
||||
(assoc root' :block/children children)
|
||||
root')))
|
||||
|
||||
(defn non-consecutive-blocks->vec-tree
|
||||
"`blocks` need to be in the same page."
|
||||
@@ -84,26 +90,15 @@
|
||||
(let [blocks (map (fn [e] {:db/id (:db/id e)
|
||||
:block/uuid (:block/uuid e)
|
||||
:block/parent {:db/id (:db/id (:block/parent e))}
|
||||
:block/left {:db/id (:db/id (:block/left e))}
|
||||
:block/page {:db/id (:db/id (:block/page e))}}) blocks)
|
||||
blocks (model/sort-page-random-blocks blocks)
|
||||
id->parent (zipmap (map :db/id blocks)
|
||||
(map (comp :db/id :block/parent) blocks))
|
||||
top-level-ids (set (remove #(id->parent (id->parent %)) (map :db/id blocks)))
|
||||
;; Separate blocks into parent and children groups [parent-children, parent-children]
|
||||
blocks' (loop [blocks blocks
|
||||
result []]
|
||||
(if-let [block (first blocks)]
|
||||
(if (top-level-ids (:db/id block))
|
||||
(let [block' (assoc block :block/level 1)]
|
||||
(recur (rest blocks) (conj result [block'])))
|
||||
(recur (rest blocks) (conj (vec (butlast result))
|
||||
(conj (last result) block))))
|
||||
result))]
|
||||
(map (fn [[parent & children]]
|
||||
(if (seq children)
|
||||
(assoc parent :block/children
|
||||
(tree children (:db/id parent)))
|
||||
parent)) blocks')))
|
||||
parent->children (group-by :block/parent blocks)
|
||||
id->blocks (zipmap (map :db/id blocks) blocks)
|
||||
top-level-blocks (filter #(nil?
|
||||
(id->blocks
|
||||
(:db/id (:block/parent (id->blocks (:db/id %)))))) blocks)
|
||||
top-level-blocks' (model/try-sort-by-left top-level-blocks (:block/parent (first top-level-blocks)))]
|
||||
(map #(tree parent->children %) top-level-blocks')))
|
||||
|
||||
(defn- sort-blocks-aux
|
||||
[parents parent-groups]
|
||||
|
||||
@@ -708,13 +708,25 @@
|
||||
[]
|
||||
(:selection/blocks @state))
|
||||
|
||||
(defn get-selection-block-ids
|
||||
[]
|
||||
(->> (sub :selection/blocks)
|
||||
(defn- get-selected-block-ids
|
||||
[blocks]
|
||||
(->> blocks
|
||||
(keep #(when-let [id (dom/attr % "blockid")]
|
||||
(uuid id)))
|
||||
(distinct)))
|
||||
|
||||
(defn get-selection-block-ids
|
||||
[]
|
||||
(get-selected-block-ids (get-selection-blocks)))
|
||||
|
||||
(defn sub-block-selected?
|
||||
[block-uuid]
|
||||
(rum/react
|
||||
(rum/derived-atom [state] [::select-block block-uuid]
|
||||
(fn [state]
|
||||
(contains? (set (get-selected-block-ids (:selection/blocks state)))
|
||||
block-uuid)))))
|
||||
|
||||
(defn get-selection-start-block-or-first
|
||||
[]
|
||||
(or (get-selection-start-block)
|
||||
@@ -732,7 +744,6 @@
|
||||
|
||||
(defn conj-selection-block!
|
||||
[block direction]
|
||||
(dom/add-class! block "selected noselect")
|
||||
(swap! state assoc
|
||||
:selection/mode true
|
||||
:selection/blocks (-> (conj (vec (:selection/blocks @state)) block)
|
||||
@@ -741,10 +752,18 @@
|
||||
|
||||
(defn drop-last-selection-block!
|
||||
[]
|
||||
(let [last-block (peek (vec (:selection/blocks @state)))]
|
||||
(let [direction (:selection/direction @state)
|
||||
up? (= direction :up)
|
||||
blocks (:selection/blocks @state)
|
||||
last-block (if up?
|
||||
(first blocks)
|
||||
(peek (vec blocks)))
|
||||
blocks' (if up?
|
||||
(rest blocks)
|
||||
(pop (vec blocks)))]
|
||||
(swap! state assoc
|
||||
:selection/mode true
|
||||
:selection/blocks (pop (vec (:selection/blocks @state))))
|
||||
:selection/blocks blocks')
|
||||
last-block))
|
||||
|
||||
(defn get-selection-direction
|
||||
@@ -1344,12 +1363,13 @@
|
||||
(>= (- now last-time) 3000)))))
|
||||
|
||||
(defn input-idle?
|
||||
[repo]
|
||||
[repo & {:keys [diff]
|
||||
:or {diff 1000}}]
|
||||
(when repo
|
||||
(or
|
||||
(when-let [last-time (get-in @state [:editor/last-input-time repo])]
|
||||
(let [now (util/time-ms)]
|
||||
(>= (- now last-time) 500)))
|
||||
(>= (- now last-time) diff)))
|
||||
;; not in editing mode
|
||||
(not (get-edit-input-id)))))
|
||||
|
||||
@@ -1652,7 +1672,8 @@
|
||||
(defn edit-in-query-or-refs-component
|
||||
[]
|
||||
(let [config (last (get-editor-args))]
|
||||
(or (:custom-query? config) (:ref? config))))
|
||||
{:custom-query? (:custom-query? config)
|
||||
:ref? (:ref? config)}))
|
||||
|
||||
(defn set-auth-id-token
|
||||
[id-token]
|
||||
|
||||
@@ -1075,6 +1075,8 @@
|
||||
(= (get-relative-path "a/b/c/d/g.org" "a/b/c/e/f.org")
|
||||
"../e/f.org"))
|
||||
|
||||
(defn keyname [key] (str (namespace key) "/" (name key)))
|
||||
|
||||
#?(:cljs
|
||||
(defn select-highlight!
|
||||
[blocks]
|
||||
@@ -1087,8 +1089,6 @@
|
||||
(doseq [block blocks]
|
||||
(d/remove-class! block "selected" "noselect"))))
|
||||
|
||||
(defn keyname [key] (str (namespace key) "/" (name key)))
|
||||
|
||||
(defn batch [in max-time handler buf-atom]
|
||||
(async/go-loop [buf buf-atom t (async/timeout max-time)]
|
||||
(let [[v p] (async/alts! [in t])]
|
||||
|
||||
Reference in New Issue
Block a user