mirror of
https://github.com/logseq/logseq.git
synced 2026-06-01 19:01:22 +00:00
Merge branch 'master' into feat/cliable
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
[frontend.db :as db]
|
||||
[frontend.db.async :as db-async]
|
||||
[frontend.db.model :as db-model]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.property.util :as pu]
|
||||
[frontend.mobile.haptics :as haptics]
|
||||
[frontend.modules.outliner.op :as outliner-op]
|
||||
@@ -149,29 +150,31 @@
|
||||
:as opts}]
|
||||
(when (and (not config/publishing?) (:block/uuid block))
|
||||
(let [repo (state/get-current-repo)]
|
||||
(p/do!
|
||||
(db-async/<get-block repo (:db/id block) {:children? false})
|
||||
(when save-code-editor? (state/pub-event! [:editor/save-code-editor]))
|
||||
(when (not= (:block/uuid block) (:block/uuid (state/get-edit-block)))
|
||||
(state/clear-edit! {:clear-editing-block? false}))
|
||||
(when-let [block-id (:block/uuid block)]
|
||||
(let [block (or (db/entity [:block/uuid block-id]) block)
|
||||
content (or custom-content (:block/title block) "")
|
||||
content-length (count content)
|
||||
text-range (cond
|
||||
(vector? pos)
|
||||
(text-range-by-lst-fst-line content pos)
|
||||
(when-let [block-id (:block/uuid block)]
|
||||
(let [block (or (db/entity [:block/uuid block-id]) block)]
|
||||
(if (ldb/recycled? block)
|
||||
(notification/show! "Recycle is read-only." :warning)
|
||||
(p/do!
|
||||
(db-async/<get-block repo (:db/id block) {:children? false})
|
||||
(when save-code-editor? (state/pub-event! [:editor/save-code-editor]))
|
||||
(when (not= (:block/uuid block) (:block/uuid (state/get-edit-block)))
|
||||
(state/clear-edit! {:clear-editing-block? false}))
|
||||
(let [content (or custom-content (:block/title block) "")
|
||||
content-length (count content)
|
||||
text-range (cond
|
||||
(vector? pos)
|
||||
(text-range-by-lst-fst-line content pos)
|
||||
|
||||
(and (> tail-len 0) (>= (count content) tail-len))
|
||||
(subs content 0 (- (count content) tail-len))
|
||||
(and (> tail-len 0) (>= (count content) tail-len))
|
||||
(subs content 0 (- (count content) tail-len))
|
||||
|
||||
(or (= :max pos) (<= content-length pos))
|
||||
content
|
||||
(or (= :max pos) (<= content-length pos))
|
||||
content
|
||||
|
||||
:else
|
||||
(subs content 0 pos))]
|
||||
(state/clear-selection!)
|
||||
(edit-block-aux repo block content text-range (assoc opts :pos pos))))))))
|
||||
:else
|
||||
(subs content 0 pos))]
|
||||
(state/clear-selection!)
|
||||
(edit-block-aux repo block content text-range (assoc opts :pos pos))))))))))
|
||||
|
||||
(defn- get-original-block-by-dom
|
||||
[node]
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
(ns frontend.handler.common.developer
|
||||
"Common fns for developer related functionality"
|
||||
(:require [cljs.pprint :as pprint]
|
||||
(:require ["/frontend/utils" :as utils]
|
||||
[cljs.pprint :as pprint]
|
||||
[clojure.string :as string]
|
||||
[datascript.impl.entity :as de]
|
||||
[frontend.db :as db]
|
||||
[frontend.format.mldoc :as mldoc]
|
||||
@@ -9,6 +11,7 @@
|
||||
[frontend.persist-db :as persist-db]
|
||||
[frontend.state :as state]
|
||||
[frontend.ui :as ui]
|
||||
[frontend.util :as util]
|
||||
[frontend.util.page :as page-util]
|
||||
[logseq.db.frontend.property :as db-property]
|
||||
[promesa.core :as p]))
|
||||
@@ -83,10 +86,50 @@
|
||||
(defn ^:export validate-db []
|
||||
(state/<invoke-db-worker :thread-api/validate-db (state/get-current-repo)))
|
||||
|
||||
(defn- checksum-export-file-name
|
||||
[repo]
|
||||
(-> (or repo "graph")
|
||||
(string/replace #"^/+" "")
|
||||
(string/replace #"[\\/]+" "_")
|
||||
(str "_checksum_" (quot (util/time-ms) 1000))))
|
||||
|
||||
(defn ^:export recompute-checksum-diagnostics
|
||||
[]
|
||||
(if-let [repo (state/get-current-repo)]
|
||||
(-> (state/<invoke-db-worker :thread-api/recompute-checksum-diagnostics repo)
|
||||
(p/then (fn [{:keys [recomputed-checksum local-checksum remote-checksum blocks checksum-attrs e2ee?]
|
||||
:as result}]
|
||||
(if (map? result)
|
||||
(let [export-edn {:repo repo
|
||||
:generated-at (.toISOString (js/Date.))
|
||||
:e2ee? e2ee?
|
||||
:recomputed-checksum recomputed-checksum
|
||||
:local-checksum local-checksum
|
||||
:remote-checksum remote-checksum
|
||||
:checksum-attrs checksum-attrs
|
||||
:blocks blocks}
|
||||
content (with-out-str (pprint/pprint export-edn))
|
||||
blob (js/Blob. #js [content] (clj->js {:type "text/edn;charset=utf-8"}))
|
||||
filename (checksum-export-file-name repo)]
|
||||
(utils/saveToFile blob filename "edn")
|
||||
(notification/show!
|
||||
(str "Checksum recomputed. Recomputed: " recomputed-checksum
|
||||
", local: " (or local-checksum "<nil>")
|
||||
", remote: " (or remote-checksum "<nil>")
|
||||
". Downloaded " filename ".edn with " (count blocks)
|
||||
" blocks and checksum attrs " (pr-str checksum-attrs) ".")
|
||||
:success
|
||||
false))
|
||||
(notification/show! "Unable to compute checksum diagnostics for current graph." :warning))))
|
||||
(p/catch (fn [error]
|
||||
(js/console.error "recompute-checksum-diagnostics failed:" error)
|
||||
(notification/show! "Failed to compute graph checksum diagnostics." :error))))
|
||||
(notification/show! "No graph found" :warning)))
|
||||
|
||||
(defn import-chosen-graph
|
||||
[repo]
|
||||
(p/let [_ (persist-db/<close-db repo)]
|
||||
(notification/show! (str "Graph updated! Switching to graph ...") :success)
|
||||
(notification/show! "Graph updated! Switching to graph ..." :success)
|
||||
(state/pub-event! [:graph/switch repo])))
|
||||
|
||||
(defn ^:export replace-graph-with-db-file []
|
||||
|
||||
@@ -2,25 +2,26 @@
|
||||
"Common fns for file and db based page handlers, including create!, delete!
|
||||
and favorite fns. This ns should be agnostic of file or db concerns but there
|
||||
is still some file-specific tech debt to remove from create!"
|
||||
(:require [clojure.set :as set]
|
||||
[clojure.string :as string]
|
||||
[datascript.core :as d]
|
||||
[dommy.core :as dom]
|
||||
[frontend.db :as db]
|
||||
[frontend.db.conn :as conn]
|
||||
[frontend.handler.config :as config-handler]
|
||||
[frontend.handler.db-based.editor :as db-editor-handler]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.handler.ui :as ui-handler]
|
||||
[frontend.modules.outliner.op :as outliner-op]
|
||||
[frontend.modules.outliner.ui :as ui-outliner-tx]
|
||||
[frontend.state :as state]
|
||||
[logseq.common.config :as common-config]
|
||||
[logseq.common.util :as common-util]
|
||||
[logseq.common.util.page-ref :as page-ref]
|
||||
[logseq.db :as ldb]
|
||||
[promesa.core :as p]))
|
||||
(:require
|
||||
[clojure.set :as set]
|
||||
[clojure.string :as string]
|
||||
[datascript.core :as d]
|
||||
[dommy.core :as dom]
|
||||
[frontend.db :as db]
|
||||
[frontend.db.conn :as conn]
|
||||
[frontend.handler.config :as config-handler]
|
||||
[frontend.handler.db-based.editor :as db-editor-handler]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.handler.ui :as ui-handler]
|
||||
[frontend.modules.outliner.op :as outliner-op]
|
||||
[frontend.modules.outliner.ui :as ui-outliner-tx]
|
||||
[frontend.state :as state]
|
||||
[logseq.common.config :as common-config]
|
||||
[logseq.common.util :as common-util]
|
||||
[logseq.common.util.page-ref :as page-ref]
|
||||
[logseq.db :as ldb]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(defn- wrap-tags
|
||||
"Tags might have multiple words"
|
||||
@@ -158,18 +159,10 @@
|
||||
;; =========
|
||||
|
||||
(defn after-page-deleted!
|
||||
[page-name tx-meta]
|
||||
;; TODO: move favorite && unfavorite to worker too
|
||||
[page-name]
|
||||
;; TODO: move favorite && unfavorite to worker too
|
||||
(when-let [page-block-uuid (:block/uuid (db/get-page page-name))]
|
||||
(<db-unfavorite-page! page-block-uuid))
|
||||
|
||||
(when (and (not= :rename-page (:real-outliner-op tx-meta))
|
||||
(= (some-> (state/get-current-page) common-util/page-name-sanity-lc)
|
||||
(common-util/page-name-sanity-lc page-name)))
|
||||
(route-handler/redirect-to-home!))
|
||||
|
||||
;; TODO: why need this?
|
||||
(ui-handler/re-render-root!))
|
||||
(<db-unfavorite-page! page-block-uuid)))
|
||||
|
||||
(defn after-page-renamed!
|
||||
[repo {:keys [page-id old-name new-name]}]
|
||||
|
||||
@@ -206,6 +206,25 @@
|
||||
true
|
||||
(true? graph-e2ee?)))
|
||||
|
||||
(defn- <ensure-user-rsa-keys-on-server!
|
||||
[{:keys [server-rsa-keys-exists?]}]
|
||||
(if (not= false server-rsa-keys-exists?)
|
||||
(p/resolved nil)
|
||||
(if @state/*db-worker
|
||||
(-> (state/<invoke-db-worker :thread-api/db-sync-ensure-user-rsa-keys
|
||||
{:ensure-server? true
|
||||
:server-rsa-keys-exists? false})
|
||||
(p/catch (fn [error]
|
||||
(log/error :db-sync/ensure-user-rsa-keys-failed
|
||||
{:error error
|
||||
:reason :server-rsa-keys-missing})
|
||||
nil)))
|
||||
(do
|
||||
(log/warn :db-sync/ensure-user-rsa-keys-skipped
|
||||
{:reason :db-worker-not-ready
|
||||
:server-rsa-keys-exists? server-rsa-keys-exists?})
|
||||
(p/resolved nil)))))
|
||||
|
||||
(defn- <wait-for-db-worker-ready!
|
||||
[]
|
||||
(if @state/*db-worker
|
||||
@@ -286,6 +305,8 @@
|
||||
base (http-base)]
|
||||
(if base
|
||||
(p/let [_ (js/Promise. user-handler/task--ensure-id&access-token)
|
||||
_ (state/<invoke-db-worker :thread-api/db-sync-ensure-user-rsa-keys
|
||||
{:ensure-server? true})
|
||||
body (coerce-http-request :graphs/create
|
||||
{:graph-name (string/replace repo config/db-version-prefix "")
|
||||
:schema-version schema-version
|
||||
@@ -411,6 +432,8 @@
|
||||
resp (fetch-json (str base "/graphs")
|
||||
{:method "GET"}
|
||||
{:response-schema :graphs/list})
|
||||
_ (<ensure-user-rsa-keys-on-server! {:server-rsa-keys-exists?
|
||||
(:user-rsa-keys-exists? resp)})
|
||||
graphs (:graphs resp)
|
||||
result (mapv (fn [graph]
|
||||
(let [graph-e2ee? (if (contains? graph :graph-e2ee?)
|
||||
|
||||
@@ -320,6 +320,7 @@
|
||||
{:outliner-op :insert-blocks}
|
||||
(save-current-block! {:current-block current-block})
|
||||
(outliner-op/insert-blocks! [new-block'] current-block {:sibling? sibling?
|
||||
:right-sibling-id (:db/id (:right-sibling config))
|
||||
:keep-uuid? keep-uuid?
|
||||
:ordered-list? ordered-list?
|
||||
:replace-empty-target? replace-empty-target?
|
||||
@@ -470,9 +471,9 @@
|
||||
|
||||
(defn insert-new-block!
|
||||
"Won't save previous block content - remember to save!"
|
||||
([state]
|
||||
(insert-new-block! state nil))
|
||||
([_state block-value]
|
||||
([state right-sibling]
|
||||
(insert-new-block! state nil right-sibling))
|
||||
([_state block-value right-sibling]
|
||||
(->
|
||||
(when (not config/publishing?)
|
||||
(when-let [state (get-state)]
|
||||
@@ -507,7 +508,7 @@
|
||||
|
||||
:else
|
||||
insert-new-block-aux!)
|
||||
[result-promise sibling? next-block] (insert-fn config block'' value)
|
||||
[result-promise sibling? next-block] (insert-fn (assoc config :right-sibling right-sibling) block'' value)
|
||||
edit-block-f (fn []
|
||||
(let [next-block' (db/entity [:block/uuid (:block/uuid next-block)])
|
||||
pos 0
|
||||
@@ -541,71 +542,72 @@
|
||||
(db/get-page page)
|
||||
(db/entity [:block/uuid block-uuid]))]
|
||||
(when block
|
||||
(let [last-block (when (not sibling?)
|
||||
(let [children (:block/_parent block)
|
||||
blocks (db/sort-by-order children)
|
||||
last-block-id (:db/id (last blocks))]
|
||||
(when last-block-id
|
||||
(db/entity last-block-id))))
|
||||
new-block (-> (select-keys block [:block/page])
|
||||
(assoc :block/title content))
|
||||
new-block (assoc new-block :block/page
|
||||
(if page
|
||||
(:db/id block)
|
||||
(:db/id (:block/page new-block))))
|
||||
new-block (-> new-block
|
||||
(wrap-parse-block)
|
||||
(assoc :block/uuid (or custom-uuid (db/new-block-id))))
|
||||
new-block (merge new-block other-attrs)
|
||||
block' (db/entity (:db/id block))
|
||||
[target-block sibling?] (cond
|
||||
before?
|
||||
(let [left-or-parent (or (ldb/get-left-sibling block)
|
||||
(:block/parent block))
|
||||
sibling? (if (= (:db/id (:block/parent block)) (:db/id left-or-parent))
|
||||
false sibling?)]
|
||||
[left-or-parent sibling?])
|
||||
(if (ldb/recycled? block)
|
||||
(notification/show! "Recycle is read-only." :warning)
|
||||
(let [last-block (when (not sibling?)
|
||||
(let [children (:block/_parent block)
|
||||
blocks (db/sort-by-order children)
|
||||
last-block-id (:db/id (last blocks))]
|
||||
(when last-block-id
|
||||
(db/entity last-block-id))))
|
||||
new-block (-> (select-keys block [:block/page])
|
||||
(assoc :block/title content))
|
||||
new-block (assoc new-block :block/page
|
||||
(if page
|
||||
(:db/id block)
|
||||
(:db/id (:block/page new-block))))
|
||||
new-block (-> new-block
|
||||
(wrap-parse-block)
|
||||
(assoc :block/uuid (or custom-uuid (db/new-block-id))))
|
||||
new-block (merge new-block other-attrs)
|
||||
block' (db/entity (:db/id block))
|
||||
[target-block sibling?] (cond
|
||||
before?
|
||||
(let [left-or-parent (or (ldb/get-left-sibling block)
|
||||
(:block/parent block))
|
||||
sibling? (if (= (:db/id (:block/parent block)) (:db/id left-or-parent))
|
||||
false sibling?)]
|
||||
[left-or-parent sibling?])
|
||||
|
||||
sibling?
|
||||
[block' sibling?]
|
||||
sibling?
|
||||
[block' sibling?]
|
||||
|
||||
start?
|
||||
[block' false]
|
||||
start?
|
||||
[block' false]
|
||||
|
||||
end?
|
||||
(if last-block
|
||||
end?
|
||||
(if last-block
|
||||
[last-block true]
|
||||
[block' false])
|
||||
|
||||
last-block
|
||||
[last-block true]
|
||||
[block' false])
|
||||
|
||||
last-block
|
||||
[last-block true]
|
||||
block
|
||||
[block' sibling?]
|
||||
|
||||
block
|
||||
[block' sibling?]
|
||||
|
||||
;; FIXME: assert
|
||||
:else
|
||||
nil)]
|
||||
(when target-block
|
||||
(p/do!
|
||||
(let [new-block' (if (seq properties)
|
||||
(into new-block properties)
|
||||
new-block)]
|
||||
(ui-outliner-tx/transact!
|
||||
{:outliner-op :insert-blocks}
|
||||
(outliner-insert-block! config target-block new-block'
|
||||
{:sibling? sibling?
|
||||
:keep-uuid? true
|
||||
:ordered-list? ordered-list?
|
||||
:outliner-op outliner-op
|
||||
:replace-empty-target? replace-empty-target?})))
|
||||
(when edit-block?
|
||||
(if (and replace-empty-target?
|
||||
(string/blank? (:block/title last-block)))
|
||||
(edit-block! last-block :max)
|
||||
(edit-block! new-block :max)))
|
||||
(when-let [id (:block/uuid new-block)]
|
||||
(db/entity [:block/uuid id])))))))))
|
||||
:else
|
||||
nil)]
|
||||
(when target-block
|
||||
(p/do!
|
||||
(let [new-block' (if (seq properties)
|
||||
(into new-block properties)
|
||||
new-block)]
|
||||
(ui-outliner-tx/transact!
|
||||
{:outliner-op :insert-blocks}
|
||||
(outliner-insert-block! config target-block new-block'
|
||||
{:sibling? sibling?
|
||||
:keep-uuid? true
|
||||
:ordered-list? ordered-list?
|
||||
:outliner-op outliner-op
|
||||
:replace-empty-target? replace-empty-target?})))
|
||||
(when edit-block?
|
||||
(if (and replace-empty-target?
|
||||
(string/blank? (:block/title last-block)))
|
||||
(edit-block! last-block :max)
|
||||
(edit-block! new-block :max)))
|
||||
(when-let [id (:block/uuid new-block)]
|
||||
(db/entity [:block/uuid id]))))))))))
|
||||
|
||||
(defn get-selected-blocks
|
||||
[]
|
||||
@@ -797,9 +799,12 @@
|
||||
(defn move-blocks!
|
||||
[blocks target opts]
|
||||
(when (seq blocks)
|
||||
(ui-outliner-tx/transact!
|
||||
{:outliner-op :move-blocks}
|
||||
(outliner-op/move-blocks! blocks target opts))))
|
||||
(if (or (some ldb/recycled? blocks)
|
||||
(ldb/recycled? target))
|
||||
(notification/show! "Recycle is read-only." :warning)
|
||||
(ui-outliner-tx/transact!
|
||||
{:outliner-op :move-blocks}
|
||||
(outliner-op/move-blocks! blocks target opts)))))
|
||||
|
||||
(defn move-selected-blocks
|
||||
[e]
|
||||
@@ -976,10 +981,11 @@
|
||||
(let [repo (state/get-current-repo)
|
||||
block-uuids (distinct (keep #(when-let [id (dom/attr % "blockid")] (uuid id)) dom-blocks))
|
||||
lookup-refs (map (fn [id] [:block/uuid id]) block-uuids)
|
||||
blocks (map db/entity lookup-refs)]
|
||||
(ui-outliner-tx/transact!
|
||||
{:outliner-op :delete-blocks}
|
||||
(let [top-level-blocks (block-handler/get-top-level-blocks blocks)]
|
||||
blocks (map db/entity lookup-refs)
|
||||
top-level-blocks (block-handler/get-top-level-blocks blocks)]
|
||||
(when-not (every? ldb/recycled? top-level-blocks)
|
||||
(ui-outliner-tx/transact!
|
||||
{:outliner-op :delete-blocks}
|
||||
(when (seq top-level-blocks)
|
||||
(let [sorted-blocks (mapcat (fn [block]
|
||||
(tree/get-sorted-block-and-children repo (:db/id block)))
|
||||
@@ -1831,6 +1837,14 @@
|
||||
(let [ids (set (map :db/id blocks))]
|
||||
(some? (some #(ids (:db/id (:block/parent %))) blocks))))
|
||||
|
||||
(defn- unrecycle-tx-data
|
||||
[root]
|
||||
[[:db/retract (:db/id root) :logseq.property/deleted-at]
|
||||
[:db/retract (:db/id root) :logseq.property/deleted-by-ref]
|
||||
[:db/retract (:db/id root) :logseq.property.recycle/original-parent]
|
||||
[:db/retract (:db/id root) :logseq.property.recycle/original-page]
|
||||
[:db/retract (:db/id root) :logseq.property.recycle/original-order]])
|
||||
|
||||
(defn paste-blocks
|
||||
"Given a vec of blocks, insert them into the target page.
|
||||
keep-uuid?: if true, keep the uuid provided in the block structure."
|
||||
@@ -1865,6 +1879,13 @@
|
||||
(or (ldb/get-left-sibling target-block)
|
||||
(:block/parent (db/entity (:db/id target-block))))
|
||||
target-block)
|
||||
existing-blocks (keep (fn [block]
|
||||
(when-let [id (:block/uuid block)]
|
||||
(db/entity [:block/uuid id])))
|
||||
blocks)
|
||||
move-from-recycle? (and keep-uuid?
|
||||
(seq existing-blocks)
|
||||
(every? ldb/recycled? existing-blocks))
|
||||
sibling? (cond
|
||||
(and paste-nested-blocks? empty-target?)
|
||||
(= (:block/parent target-block') (:block/parent target-block))
|
||||
@@ -1877,20 +1898,32 @@
|
||||
|
||||
:else
|
||||
true)
|
||||
transact-blocks! #(ui-outliner-tx/transact!
|
||||
{:outliner-op :insert-blocks
|
||||
:additional-tx revert-cut-txs}
|
||||
(when target-block'
|
||||
(let [format (get target-block' :block/format :markdown)
|
||||
repo (state/get-current-repo)
|
||||
blocks' (map (fn [block]
|
||||
(paste-block-cleanup repo block page exclude-properties format content-update-fn keep-uuid?))
|
||||
blocks)]
|
||||
(outliner-op/insert-blocks! blocks' target-block' {:sibling? sibling?
|
||||
:outliner-op :paste
|
||||
:outliner-real-op outliner-real-op
|
||||
:replace-empty-target? replace-empty-target?
|
||||
:keep-uuid? keep-uuid?}))))]
|
||||
transact-blocks! #(if move-from-recycle?
|
||||
(ui-outliner-tx/transact!
|
||||
{:outliner-op :move-blocks
|
||||
:additional-tx revert-cut-txs}
|
||||
(when target-block'
|
||||
(let [top-level-blocks (block-handler/get-top-level-blocks existing-blocks)
|
||||
unrecycle-tx (mapcat unrecycle-tx-data top-level-blocks)]
|
||||
(when (seq unrecycle-tx)
|
||||
(outliner-op/transact! unrecycle-tx nil))
|
||||
(outliner-op/move-blocks! top-level-blocks target-block'
|
||||
{:sibling? sibling?
|
||||
:outliner-op :paste}))))
|
||||
(ui-outliner-tx/transact!
|
||||
{:outliner-op :insert-blocks
|
||||
:additional-tx revert-cut-txs}
|
||||
(when target-block'
|
||||
(let [format (get target-block' :block/format :markdown)
|
||||
repo (state/get-current-repo)
|
||||
blocks' (map (fn [block]
|
||||
(paste-block-cleanup repo block page exclude-properties format content-update-fn keep-uuid?))
|
||||
blocks)]
|
||||
(outliner-op/insert-blocks! blocks' target-block' {:sibling? sibling?
|
||||
:outliner-op :paste
|
||||
:outliner-real-op outliner-real-op
|
||||
:replace-empty-target? replace-empty-target?
|
||||
:keep-uuid? keep-uuid?})))))]
|
||||
(if ops-only?
|
||||
(transact-blocks!)
|
||||
(p/let [_ (when has-unsaved-edits
|
||||
@@ -1950,51 +1983,26 @@
|
||||
(insert-template! element-id db-id {}))
|
||||
([element-id db-id {:keys [target] :as opts}]
|
||||
(let [repo (state/get-current-repo)]
|
||||
(p/let [block (db-async/<pull repo db-id)
|
||||
block (when (:block/uuid block)
|
||||
(db-async/<get-block repo (:block/uuid block)
|
||||
{:children? true}))]
|
||||
(p/let [block (db-async/<get-block repo db-id {:children? false})]
|
||||
(when (:db/id block)
|
||||
(let [journal? (ldb/journal? target)
|
||||
target (or target (state/get-edit-block))
|
||||
format (get block :block/format :markdown)
|
||||
block-uuid (:block/uuid block)
|
||||
blocks (db/get-block-and-children repo block-uuid {:include-property-block? true})
|
||||
sorted-blocks (let [blocks' (rest blocks)]
|
||||
(cons
|
||||
(-> (first blocks')
|
||||
(assoc :logseq.property/used-template (:db/id block)))
|
||||
(rest blocks')))
|
||||
blocks sorted-blocks]
|
||||
format (get block :block/format :markdown)]
|
||||
(when element-id
|
||||
(insert-command! element-id "" format {:end-pattern commands/command-trigger}))
|
||||
(let [sibling? (:sibling? opts)
|
||||
sibling?' (cond
|
||||
(some? sibling?)
|
||||
sibling?
|
||||
(try
|
||||
(p/let [result (ui-outliner-tx/transact!
|
||||
{:outliner-op :apply-template
|
||||
:created-from-journal-template? journal?}
|
||||
(when-not (string/blank? (state/get-edit-content))
|
||||
(save-current-block!))
|
||||
(outliner-op/apply-template! db-id target opts))]
|
||||
(when result (edit-last-block-after-inserted! result)))
|
||||
|
||||
(db/has-children? (:block/uuid target))
|
||||
false
|
||||
|
||||
:else
|
||||
true)]
|
||||
(when (seq blocks)
|
||||
(try
|
||||
(p/let [result (ui-outliner-tx/transact!
|
||||
{:outliner-op :insert-blocks
|
||||
:created-from-journal-template? journal?}
|
||||
(when-not (string/blank? (state/get-edit-content))
|
||||
(save-current-block!))
|
||||
(outliner-op/insert-blocks! blocks target
|
||||
(assoc opts
|
||||
:sibling? sibling?'
|
||||
:insert-template? true)))]
|
||||
(when result (edit-last-block-after-inserted! result)))
|
||||
|
||||
(catch :default ^js/Error e
|
||||
(notification/show!
|
||||
(util/format "Template insert error: %s" (.-message e))
|
||||
:error)))))))))))
|
||||
(catch :default ^js/Error e
|
||||
(notification/show!
|
||||
(util/format "Template insert error: %s" (.-message e))
|
||||
:error)))))))))
|
||||
|
||||
(defn template-on-chosen-handler
|
||||
[element-id]
|
||||
@@ -2063,7 +2071,7 @@
|
||||
input (state/get-input)
|
||||
config (assoc config :keydown-new-block true)
|
||||
content (gobj/get input "value")
|
||||
has-right? (ldb/get-right-sibling block)]
|
||||
right-sibling (ldb/get-right-sibling block)]
|
||||
(cond
|
||||
(and (string/blank? content)
|
||||
(own-order-number-list? block)
|
||||
@@ -2073,12 +2081,12 @@
|
||||
|
||||
(and
|
||||
(string/blank? content)
|
||||
(not has-right?)
|
||||
(not right-sibling)
|
||||
(not (last-top-level-child? config block)))
|
||||
(indent-outdent false)
|
||||
|
||||
:else
|
||||
(insert-new-block! state)))))))
|
||||
(insert-new-block! state right-sibling)))))))
|
||||
|
||||
(defn- inside-of-single-block
|
||||
"When we are in a single block wrapper, we should always insert a new line instead of new block"
|
||||
@@ -3074,8 +3082,7 @@
|
||||
(:block/uuid page-entity)))
|
||||
repo (state/get-current-repo)
|
||||
_ (db-async/<get-block repo (or block-id page-id)
|
||||
{:children? true
|
||||
:include-collapsed-children? true})
|
||||
{:include-collapsed-children? true})
|
||||
entity (db/entity [:block/uuid (or block-id page-id)])
|
||||
result (or (:block/_page entity)
|
||||
(rest (db/get-block-and-children repo (:block/uuid entity))))
|
||||
@@ -3151,8 +3158,7 @@
|
||||
(defn expand-block! [block-id & {:keys [skip-db-collpsing?]}]
|
||||
(let [repo (state/get-current-repo)]
|
||||
(p/do!
|
||||
(db-async/<get-block repo block-id {:children? true
|
||||
:include-collapsed-children? true})
|
||||
(db-async/<get-block repo block-id {:include-collapsed-children? true})
|
||||
(when-not (or skip-db-collpsing? (skip-collapsing-in-db?))
|
||||
(set-blocks-collapsed! [block-id] false))
|
||||
(state/set-collapsed-block! block-id false))))
|
||||
@@ -3492,9 +3498,9 @@
|
||||
(ui-outliner-tx/transact!
|
||||
{:outliner-op :save-block}
|
||||
(property-handler/set-block-property! (:db/id block) :block/tags :logseq.class/Query)
|
||||
(save-block-inner! block "" {})
|
||||
(when query-block
|
||||
(save-block-inner! query-block current-query {}))))))))
|
||||
(save-block-inner! query-block current-query {}))
|
||||
(save-block-inner! block "" {})))))))
|
||||
|
||||
(defn quick-add-ensure-new-block-exists!
|
||||
[]
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[frontend.db :as db]
|
||||
[frontend.handler.editor :as editor-handler]
|
||||
[frontend.state :as state]
|
||||
[frontend.undo-redo :as undo-redo]
|
||||
[frontend.util :as util]
|
||||
[goog.dom :as gdom]))
|
||||
|
||||
@@ -30,9 +29,12 @@
|
||||
;; skip recording editor info when undo or redo is still running
|
||||
(when-not (contains? #{:undo :redo} @(:editor/op @state/state))
|
||||
(let [page-id (:block/uuid (:block/page (db/entity (:db/id (state/get-edit-block)))))
|
||||
repo (state/get-current-repo)]
|
||||
repo (state/get-current-repo)
|
||||
editor-info (state/get-editor-info)]
|
||||
(when page-id
|
||||
(undo-redo/record-editor-info! repo (state/get-editor-info)))))
|
||||
(state/<invoke-db-worker :thread-api/undo-redo-record-editor-info
|
||||
repo
|
||||
editor-info))))
|
||||
(state/set-state! :editor/op nil))
|
||||
state)
|
||||
|
||||
|
||||
@@ -56,6 +56,12 @@
|
||||
(defmulti handle first)
|
||||
|
||||
(defonce ^:private *search-index-build-timeout (atom nil))
|
||||
(def ^:private decrypt-aes-key-failed-notification
|
||||
"Failed to decrypt this graph.")
|
||||
|
||||
(defn- decrypt-aes-key-failed?
|
||||
[error]
|
||||
(string/includes? (or (ex-message error) (str error)) "decrypt-aes-key"))
|
||||
|
||||
(defn- schedule-search-index-build!
|
||||
[repo]
|
||||
@@ -132,9 +138,10 @@
|
||||
(page-handler/create-today-journal!)
|
||||
(page-handler/<create! page-name opts)))
|
||||
|
||||
(defmethod handle :page/deleted [[_ page-name tx-meta]]
|
||||
(when-not (util/mobile?)
|
||||
(page-common-handler/after-page-deleted! page-name tx-meta)))
|
||||
(defmethod handle :page/deleted [[_ page-name _tx-meta]]
|
||||
(when page-name
|
||||
(when-not (util/mobile?)
|
||||
(page-common-handler/after-page-deleted! page-name))))
|
||||
|
||||
(defmethod handle :page/renamed [[_ repo data]]
|
||||
(when-not (util/mobile?)
|
||||
@@ -384,8 +391,8 @@
|
||||
(println "RTC download graph failed, error:")
|
||||
(log/error :rtc-download-graph-failed e)
|
||||
(shui/popup-hide! :download-rtc-graph)
|
||||
;; TODO: notify error
|
||||
))))
|
||||
(when (decrypt-aes-key-failed? e)
|
||||
(notification/show! decrypt-aes-key-failed-notification :error false))))))
|
||||
|
||||
;; db-worker -> UI
|
||||
(defmethod handle :db/sync-changes [[_ data]]
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
(ns frontend.handler.export.common
|
||||
"common fns for exporting.
|
||||
exclude some fns which produce lazy-seq, which can cause strange behaviors
|
||||
when use together with dynamic var."
|
||||
(:refer-clojure :exclude [map filter mapcat concat remove])
|
||||
"Common functions for exporting."
|
||||
(:require [clojure.string :as string]
|
||||
[frontend.db.conn :as conn]
|
||||
[frontend.state :as state]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns frontend.handler.export.opml
|
||||
"export blocks/pages as opml"
|
||||
(:refer-clojure :exclude [map filter mapcat concat remove newline])
|
||||
(:require ["/frontend/utils" :as utils]
|
||||
[clojure.string :as string]
|
||||
[clojure.zip :as z]
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.persist-db.browser :as db-browser]
|
||||
[frontend.state :as state]
|
||||
[frontend.undo-redo :as undo-redo]
|
||||
[frontend.util :as util]
|
||||
[goog.functions :refer [debounce]]
|
||||
[logseq.db :as ldb]
|
||||
@@ -12,12 +11,21 @@
|
||||
|
||||
(defn- restore-cursor!
|
||||
[{:keys [editor-cursors block-content undo?]}]
|
||||
(let [{:keys [block-uuid container-id start-pos end-pos]} (if undo? (first editor-cursors) (or (last editor-cursors) (first editor-cursors)))
|
||||
(let [cursor (if undo?
|
||||
(first editor-cursors)
|
||||
(or (last editor-cursors) (first editor-cursors)))
|
||||
{:keys [selected-block-uuids selection-direction block-uuid container-id start-pos end-pos]} cursor
|
||||
selected-blocks (when (seq selected-block-uuids)
|
||||
(->> selected-block-uuids
|
||||
(mapcat util/get-blocks-by-id)
|
||||
vec))
|
||||
pos (if undo? (or start-pos end-pos) (or end-pos start-pos))]
|
||||
(when-let [block (db/pull [:block/uuid block-uuid])]
|
||||
(editor/edit-block! block pos
|
||||
{:container-id container-id
|
||||
:custom-content block-content}))))
|
||||
(if (seq selected-blocks)
|
||||
(state/exit-editing-and-set-selected-blocks! selected-blocks selection-direction)
|
||||
(when-let [block (db/pull [:block/uuid block-uuid])]
|
||||
(editor/edit-block! block pos
|
||||
{:container-id container-id
|
||||
:custom-content block-content})))))
|
||||
|
||||
(defn- restore-app-state!
|
||||
[state]
|
||||
@@ -52,7 +60,7 @@
|
||||
(state/set-state! [:editor/last-replace-ref-content-tx repo] nil)
|
||||
(editor/save-current-block!)
|
||||
(state/clear-editor-action!)
|
||||
(reset! *last-request (undo-redo/undo repo))
|
||||
(reset! *last-request (state/<invoke-db-worker :thread-api/undo-redo-undo repo))
|
||||
(p/let [result @*last-request]
|
||||
(restore-cursor-and-state! result))))))))
|
||||
(defonce undo! (debounce undo-aux! 20))
|
||||
@@ -67,7 +75,7 @@
|
||||
(when-let [repo (state/get-current-repo)]
|
||||
(util/stop e)
|
||||
(state/clear-editor-action!)
|
||||
(reset! *last-request (undo-redo/redo repo))
|
||||
(reset! *last-request (state/<invoke-db-worker :thread-api/undo-redo-redo repo))
|
||||
(p/let [result @*last-request]
|
||||
(restore-cursor-and-state! result)))))))
|
||||
(defonce redo! (debounce redo-aux! 20))
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.handler.property :as property-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.modules.outliner.op :as outliner-op]
|
||||
[frontend.modules.outliner.ui :as ui-outliner-tx]
|
||||
[frontend.state :as state]
|
||||
@@ -31,11 +32,31 @@
|
||||
[logseq.common.util.page-ref :as page-ref]
|
||||
[logseq.db :as ldb]
|
||||
[logseq.graph-parser.text :as text]
|
||||
[logseq.outliner.recycle :as outliner-recycle]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(def <create! page-common-handler/<create!)
|
||||
(def <delete! page-common-handler/<delete!)
|
||||
|
||||
(defn get-recycle-page
|
||||
[]
|
||||
(db/get-page common-config/recycle-page-name))
|
||||
|
||||
(defn open-recycle!
|
||||
[]
|
||||
(when-let [page (get-recycle-page)]
|
||||
(route-handler/redirect-to-page! (:block/uuid page))))
|
||||
|
||||
(defn restore-recycled!
|
||||
[root-uuid]
|
||||
(when-let [root (db/entity [:block/uuid root-uuid])]
|
||||
(when-let [tx-data (seq (outliner-recycle/restore-tx-data (db/get-db) root))]
|
||||
(p/do!
|
||||
(ui-outliner-tx/transact!
|
||||
{:outliner-op :restore-recycled}
|
||||
(outliner-op/transact! tx-data nil))
|
||||
true))))
|
||||
|
||||
(defn <unfavorite-page!
|
||||
[page-name]
|
||||
(p/do!
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
(notification/show!
|
||||
(str
|
||||
(if (= :error type) "[Error]" "")
|
||||
(str "<" (:id payload) "> ")
|
||||
"<" (:id payload) "> "
|
||||
msg) type)))
|
||||
|
||||
(when-not fake-error?
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns frontend.handler.repo
|
||||
"System-component-like ns that manages user's repos/graphs"
|
||||
(:refer-clojure :exclude [clone])
|
||||
(:require [clojure.string :as string]
|
||||
[electron.ipc :as ipc]
|
||||
[frontend.config :as config]
|
||||
@@ -17,7 +16,6 @@
|
||||
[frontend.persist-db :as persist-db]
|
||||
[frontend.search :as search]
|
||||
[frontend.state :as state]
|
||||
[frontend.undo-redo :as undo-redo]
|
||||
[frontend.util :as util]
|
||||
[frontend.util.text :as text-util]
|
||||
[logseq.db.frontend.schema :as db-schema]
|
||||
@@ -52,10 +50,7 @@
|
||||
(defn start-repo-db-if-not-exists!
|
||||
[repo & {:as opts}]
|
||||
(state/set-current-repo! repo)
|
||||
(db/start-db-conn! repo (assoc opts
|
||||
:db-graph? true
|
||||
:listen-handler (fn [conn]
|
||||
(undo-redo/listen-db-changes! repo conn)))))
|
||||
(db/start-db-conn! repo (assoc opts :db-graph? true)))
|
||||
|
||||
(defn restore-and-setup-repo!
|
||||
"Restore the db of a graph from the persisted data, and setup. Create a new
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
(and (string? page-name) (not (string/blank? page-name))))
|
||||
(let [page (db/get-page page-name)]
|
||||
(if (and (not config/dev?)
|
||||
(not= common-config/recycle-page-name (:block/title page))
|
||||
(or (and (ldb/hidden? page) (not (ldb/property? page)))
|
||||
(and (ldb/built-in? page) (ldb/private-built-in-page? page))))
|
||||
(notification/show! "Cannot go to an internal page." :warning)
|
||||
|
||||
@@ -238,6 +238,14 @@
|
||||
(auto-fill-refresh-token-from-cognito!)
|
||||
(state/pub-event! [:user/fetch-info-and-graphs]))
|
||||
|
||||
(defn- clear-e2ee-password!
|
||||
[]
|
||||
(when @state/*db-worker
|
||||
(-> (state/<invoke-db-worker :thread-api/clear-e2ee-password)
|
||||
(p/catch (fn [error]
|
||||
(js/console.warn :clear-e2ee-password-failed error)
|
||||
nil)))))
|
||||
|
||||
(defn ^:export login-with-username-password-e2e
|
||||
[username' password client-id client-secret]
|
||||
(let [text-encoder (new js/TextEncoder)
|
||||
@@ -265,7 +273,9 @@
|
||||
{:id-token id-token :access-token access-token :refresh-token refresh-token})))))
|
||||
|
||||
(defn logout []
|
||||
(clear-e2ee-password!)
|
||||
(clear-tokens)
|
||||
(.clear js/localStorage)
|
||||
(state/clear-user-info!)
|
||||
(state/pub-event! [:user/logout])
|
||||
(reset! flows/*current-login-user :logout))
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[clojure.string :as string]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.state :as state]
|
||||
[frontend.undo-redo :as undo-redo]
|
||||
[lambdaisland.glogi :as log]
|
||||
[logseq.db :as ldb]))
|
||||
|
||||
@@ -30,9 +29,6 @@
|
||||
(defmethod handle :sync-db-changes [_ _worker data]
|
||||
(state/pub-event! [:db/sync-changes data]))
|
||||
|
||||
(defmethod handle :clear-undo-history [_ _worker [repo]]
|
||||
(undo-redo/clear-history! repo))
|
||||
|
||||
(defmethod handle :rtc-log [_ _worker log]
|
||||
(state/pub-event! [:rtc/log log]))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user