diff --git a/README.md b/README.md index 52a3f0f329..bcf5e786ba 100644 --- a/README.md +++ b/README.md @@ -68,11 +68,16 @@ ## 🚀 Database Version -The Database version (DB version) of Logseq introduces DB graphs while maintaining support for file graphs. [See this page](https://github.com/logseq/docs/blob/master/db-version.md) to get an overview of the main features for DB graphs. If you are an existing user, [see this page](https://github.com/logseq/docs/blob/master/db-version-changes.md) to get an overview of changes with the DB version. +The Database version (DB version) of Logseq introduces DB graphs while maintaining support for file graphs. [See this page](https://github.com/logseq/docs/blob/master/db-version.md) to get an overview of the main features for DB graphs. If you are an existing user, [see changes with the DB version](https://github.com/logseq/docs/blob/master/db-version-changes.md). The DB version has its own new mobile app! To participate in the mobile app alpha, [please complete this brief form](https://forms.gle/nfefJv51jUuULbFB9). The DB version also has a new sync approach, RTC (Real Time Collaboration)! You can use it to sync graphs between multiple devices or collaborate with others. To participate in the RTC alpha, [please fill out this form](https://forms.gle/YSyF4WfKPSDuwyjH6). -The DB version of Logseq is alpha software. When using DB graphs, we recommend you create a dedicated test graph and choose one project/workflow that’s not crucial for you. **Data loss is possible**, which is why we recommend [automated backups](https://github.com/logseq/docs/blob/master/db-version.md#automated-backup) or making [regular SQLite DB backups](https://github.com/logseq/docs/blob/master/db-version.md#graph-export). When using file graphs, **data corruption is possible** as some file content can be duplicated. We only recommend using file graphs if you are making regular backups with git. +The DB version is in beta status while the new mobile app and RTC is in alpha. This means that **data loss is possible** so we recommend [automated backups](https://github.com/logseq/docs/blob/master/db-version.md#automated-backup) or [regular SQLite DB backups](https://github.com/logseq/docs/blob/master/db-version.md#graph-export). When using DB graphs, we recommend you create a dedicated test graph and choose one project that’s not crucial for you. When using file graphs, **data corruption is possible** as some file content can be duplicated. We only recommend using it with file graphs if you make regular backups with git. -To try the latest web version, go to https://test.logseq.com/. For DB version issues, please report them to https://github.com/logseq/db-test/issues. To try the latest desktop version, go to https://github.com/logseq/logseq/actions/workflows/build-desktop-release.yml and click on the latest release. Scroll to the bottom and under the `Artifacts` section download the artifact for your operating system. +To get started with the DB version: +* To try the latest web version, go to https://test.logseq.com/. +* To try the latest desktop version, login to Github and go to https://github.com/logseq/logseq/actions/workflows/build-desktop-release.yml and click on the latest release. Scroll to the bottom and under the `Artifacts` section download the artifact for your operating system. +* To report bugs, please file them at https://github.com/logseq/db-test/issues. +* For feature or enhancement requests, please file them on Discord on the `#db-feedback` channel. +* For discussion, see the `#db-chat` channel in Discord. ## 🤔 Why Logseq? diff --git a/scripts/src/logseq/tasks/dev/db_and_file_graphs.clj b/scripts/src/logseq/tasks/dev/db_and_file_graphs.clj index 8f98a10614..34801e390f 100644 --- a/scripts/src/logseq/tasks/dev/db_and_file_graphs.clj +++ b/scripts/src/logseq/tasks/dev/db_and_file_graphs.clj @@ -110,7 +110,8 @@ ;; Use file-entity-util and entity-util when in a single graph context "ldb/whiteboard\\?" "ldb/journal\\?" "ldb/page\\?"] res (grep-many multi-graph-fns (into file-graph-paths db-graph-paths))] - (when-not (and (= 1 (:exit res)) (= "" (:out res))) + (when-not (or (and (= 1 (:exit res)) (= "" (:out res))) + (and (zero? (:exit res)) (string/starts-with? (:out res) "src/main/mobile/components/app.cljs:"))) (println "The following files should not have fns meant to be used in multi-graph contexts:") (println (:out res)) (System/exit 1)))) diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index 3d6ec8a98b..82235b2254 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -1157,23 +1157,24 @@ (excalidraw uuid-or-title (:block/uuid config))] :else - [:span.page-reference - {:data-ref (str uuid-or-title)} - (when brackets? - [:span.text-gray-500.bracket page-ref/left-brackets]) - (when (and (config/db-based-graph?) (ldb/class-instance? (db/entity :logseq.class/Task) block)) - [:div.inline-block - {:style {:margin-right 1 - :margin-top -2 - :vertical-align "middle"} - :on-pointer-down (fn [e] - (util/stop e))} - (block-positioned-properties config block :block-left)]) - (page-cp config' (if (uuid? uuid-or-title) - {:block/uuid uuid-or-title} - {:block/name uuid-or-title})) - (when brackets? - [:span.text-gray-500.bracket page-ref/right-brackets])]))))))) + (let [blank-title? (string/blank? (:block/title block))] + [:span.page-reference + {:data-ref (str uuid-or-title)} + (when (and brackets? (not blank-title?)) + [:span.text-gray-500.bracket page-ref/left-brackets]) + (when (and (config/db-based-graph?) (ldb/class-instance? (db/entity :logseq.class/Task) block)) + [:div.inline-block + {:style {:margin-right 1 + :margin-top -2 + :vertical-align "middle"} + :on-pointer-down (fn [e] + (util/stop e))} + (block-positioned-properties config block :block-left)]) + (page-cp config' (if (uuid? uuid-or-title) + {:block/uuid uuid-or-title} + {:block/name uuid-or-title})) + (when (and brackets? (not blank-title?)) + [:span.text-gray-500.bracket page-ref/right-brackets])])))))))) (defn- latex-environment-content [name option content] @@ -2844,10 +2845,7 @@ (:block/tags block) (remove (fn [t] (or (ldb/inline-tag? (:block/raw-title block) t) - (if (contains? t :logseq.property.class/hide-from-node) - (:logseq.property.class/hide-from-node t) - ;; Mobile app hides by default while everything else doesn't - (if (util/capacitor-new?) true false)) + (:logseq.property.class/hide-from-node t) (contains? hidden-internal-tags (:db/ident t)) (and (util/mobile?) (= (:db/ident t) :logseq.class/Task)))))) popup-opts {:align :end diff --git a/src/main/frontend/components/property.cljs b/src/main/frontend/components/property.cljs index f6c7a2c69a..2ec6993f48 100644 --- a/src/main/frontend/components/property.cljs +++ b/src/main/frontend/components/property.cljs @@ -493,7 +493,7 @@ [:div.ls-block.property-value-container.flex.flex-row.gap-1.items-start (when-not (or block? (and property-desc (:class-schema? opts))) - [:div.flex.h-6.items-center + [:div.flex.items-center {:style {:height 28}} [:div {:class "pl-1.5 -mr-[3px] opacity-60"} [:span.bullet-container [:span.bullet]]]]) [:div.flex.flex-1 diff --git a/src/main/frontend/components/quick_add.cljs b/src/main/frontend/components/quick_add.cljs index b86601a84d..a3e3420352 100644 --- a/src/main/frontend/components/quick_add.cljs +++ b/src/main/frontend/components/quick_add.cljs @@ -19,14 +19,18 @@ :will-unmount (fn [state] (state/clear-edit!) (state/clear-selection!) - state)} + state) + :did-mount (fn [state] + (when-not (util/mobile?) + (editor-handler/quick-add-open-last-block!)) + state)} [] (when (model/get-journal-page (date/today)) (when-let [add-page (ldb/get-built-in-page (db/get-db) common-config/quick-add-page-name)] (let [mobile? (util/mobile?) add-button [:div (shui/button - {:variant (if mobile? :default :outline) + {:variant :default :size :sm :on-click (fn [_e] (editor-handler/quick-add-blocks!))} @@ -35,13 +39,11 @@ [:div.ls-quick-add.flex.flex-1.flex-col.w-full.gap-4 [:div.border-b.pb-4.flex.flex-row.justify-between.gap-4.items-center [:div.font-medium - {:class (when-not mobile? "text-xs")} "Quick add"] (when mobile? add-button)] [:div.content {:class (if mobile? "flex flex-1 flex-col w-full" "block -ml-6")} - (page/page-blocks-cp add-page {}) - (when-not mobile? - add-button)]])))) + (page/page-blocks-cp add-page {})] + (when-not mobile? add-button)])))) diff --git a/src/main/frontend/components/repo.cljs b/src/main/frontend/components/repo.cljs index 97a18269c3..0fb61bd8a3 100644 --- a/src/main/frontend/components/repo.cljs +++ b/src/main/frontend/components/repo.cljs @@ -126,7 +126,9 @@ (repo-handler/remove-repo! repo) (state/pub-event! [:graph/unlinked repo (state/get-current-repo)]))))))} "Delete local graph")) - (when (and db-based? root (not remote?)) + (when (and db-based? root + (not remote?) + (= url (state/get-current-repo))) (shui/dropdown-menu-item {:key "logseq-sync" :class "use-logseq-sync-menu-item" @@ -141,11 +143,14 @@ (shui/popup-show! nil (fn [] (rtc-indicator/uploading-logs)) - {:id :rtc-graph-upload-log}) - (rtc-indicator/on-upload-finished-task - (fn [] - (shui/popup-hide! :rtc-graph-upload-log) - (rtc-flows/trigger-rtc-start repo)))))))} + {:id :rtc-graph-upload-log})) + + (rtc-indicator/on-upload-finished-task + (fn [] + (when (util/mobile?) (shui/popup-hide! :rtc-graph-upload-log)) + (p/do! + (rtc-flows/trigger-rtc-start repo) + (rtc-handler/p (file-sync/title file-name) + file-name-without-ext* (db-asset/asset-name->title file-name) + file-name-without-ext (if (= file-name-without-ext* "image") + (date/get-date-time-string-2) + file-name-without-ext*) checksum (assets-handler/get-file-checksum file) existing-asset (db-async/ (c.m/throttle 100 db-updated-flow))] (datom-count-fn @conn)))))) - -(defn reset-client-op-conn - [repo] - (when-let [conn (worker-state/get-client-ops-conn repo)] - (let [tx-data (->> (concat (d/datoms @conn :avet :graph-uuid) - (d/datoms @conn :avet :local-tx) - (d/datoms @conn :avet :aes-key-jwk) - (d/datoms @conn :avet :block/uuid)) - (map (fn [datom] [:db/retractEntity (:e datom)])))] - (d/transact! conn tx-data)))) diff --git a/src/main/frontend/worker/rtc/core.cljs b/src/main/frontend/worker/rtc/core.cljs index e4c15bea66..b5ec8ffa25 100644 --- a/src/main/frontend/worker/rtc/core.cljs +++ b/src/main/frontend/worker/rtc/core.cljs @@ -9,6 +9,7 @@ [frontend.worker.rtc.branch-graph :as r.branch-graph] [frontend.worker.rtc.client :as r.client] [frontend.worker.rtc.client-op :as client-op] + [frontend.worker.rtc.db :as rtc-db] [frontend.worker.rtc.exception :as r.ex] [frontend.worker.rtc.full-upload-download-graph :as r.upload-download] [frontend.worker.rtc.log-and-state :as rtc-log-and-state] @@ -370,7 +371,9 @@ (log/info :rtc-loop-task e))) start-ex (m/? onstarted-task)] (if (instance? ExceptionInfo start-ex) - start-ex + (do + (canceler) + start-ex) (do (reset! *rtc-loop-metadata {:repo repo :graph-uuid graph-uuid :local-graph-schema-version schema-version @@ -442,7 +445,14 @@ {:action "delete-graph" :graph-uuid graph-uuid :schema-version (str schema-version)}))] - (when ex-data (log/info ::delete-graph-failed {:graph-uuid graph-uuid :ex-data ex-data})) + (if ex-data + (log/info ::delete-graph-failed {:graph-uuid graph-uuid :ex-data ex-data}) + ;; Clean up rtc data in existing dbs so that the graph can be uploaded again + (when-let [repo (worker-state/get-current-repo)] + (when-let [conn (worker-state/get-datascript-conn repo)] + (let [graph-id (ldb/get-graph-rtc-uuid @conn)] + (when (= (str graph-id) (str graph-uuid)) + (rtc-db/remove-rtc-data-in-conn! repo)))))) (boolean (nil? ex-data)))))) (defn new-task--get-users-info diff --git a/src/main/frontend/worker/rtc/db.cljs b/src/main/frontend/worker/rtc/db.cljs new file mode 100644 index 0000000000..ad574e495c --- /dev/null +++ b/src/main/frontend/worker/rtc/db.cljs @@ -0,0 +1,26 @@ +(ns frontend.worker.rtc.db + "rtc db ops" + (:require [datascript.core :as d] + [frontend.worker.state :as worker-state])) + +(defn remove-rtc-data-from-local-db! + [repo] + (when-let [conn (worker-state/get-datascript-conn repo)] + (d/transact! conn [[:db/retractEntity :logseq.kv/graph-uuid] + [:db/retractEntity :logseq.kv/graph-local-tx] + [:db/retractEntity :logseq.kv/remote-schema-version]]))) + +(defn reset-client-op-conn + [repo] + (when-let [conn (worker-state/get-client-ops-conn repo)] + (let [tx-data (->> (concat (d/datoms @conn :avet :graph-uuid) + (d/datoms @conn :avet :local-tx) + (d/datoms @conn :avet :aes-key-jwk) + (d/datoms @conn :avet :block/uuid)) + (map (fn [datom] [:db/retractEntity (:e datom)])))] + (d/transact! conn tx-data)))) + +(defn remove-rtc-data-in-conn! + [repo] + (remove-rtc-data-from-local-db! repo) + (reset-client-op-conn repo)) diff --git a/src/main/frontend/worker/rtc/full_upload_download_graph.cljs b/src/main/frontend/worker/rtc/full_upload_download_graph.cljs index 2cf1a69a34..8f366100b0 100644 --- a/src/main/frontend/worker/rtc/full_upload_download_graph.cljs +++ b/src/main/frontend/worker/rtc/full_upload_download_graph.cljs @@ -11,6 +11,7 @@ [frontend.worker.db-metadata :as worker-db-metadata] [frontend.worker.rtc.client-op :as client-op] [frontend.worker.rtc.const :as rtc-const] + [frontend.worker.rtc.db :as rtc-db] [frontend.worker.rtc.log-and-state :as rtc-log-and-state] [frontend.worker.rtc.ws-util :as ws-util] [frontend.worker.shared-service :as shared-service] @@ -120,14 +121,6 @@ (:db/ident block) (update :db/ident ldb/read-transit-str) (:block/order block) (update :block/order ldb/read-transit-str))))))) -(defn- remove-rtc-data-in-conn! - [repo] - (client-op/reset-client-op-conn repo) - (when-let [conn (worker-state/get-datascript-conn repo)] - (d/transact! conn [[:db/retractEntity :logseq.kv/graph-uuid] - [:db/retractEntity :logseq.kv/graph-local-tx] - [:db/retractEntity :logseq.kv/remote-schema-version]]))) - (defn new-task--upload-graph [get-ws-create-task repo conn remote-graph-name major-schema-version] (m/sp @@ -477,7 +470,7 @@ (m/sp (rtc-log-and-state/rtc-log :rtc.log/branch-graph {:sub-type :fetching-presigned-put-url :message "fetching presigned put-url"}) - (remove-rtc-data-in-conn! repo) + (rtc-db/remove-rtc-data-in-conn! repo) (let [[{:keys [url key]} all-blocks-str] (m/? (m/join diff --git a/src/main/frontend/worker/rtc/ws_util.cljs b/src/main/frontend/worker/rtc/ws_util.cljs index 704f92f274..ae0fa6ddc9 100644 --- a/src/main/frontend/worker/rtc/ws_util.cljs +++ b/src/main/frontend/worker/rtc/ws_util.cljs @@ -1,16 +1,21 @@ (ns frontend.worker.rtc.ws-util "Add RTC related logic to the function based on ws." (:require [cljs-http-missionary.client :as http] + [frontend.worker.rtc.db :as rtc-db] [frontend.worker.rtc.exception :as r.ex] [frontend.worker.rtc.malli-schema :as rtc-schema] [frontend.worker.rtc.ws :as ws] [frontend.worker.state :as worker-state] + [frontend.worker.util :as worker-util] [goog.string :as gstring] [logseq.graph-parser.utf8 :as utf8] [missionary.core :as m])) (defn- handle-remote-ex [resp] + (when (= :graph-not-exist (:type (:ex-data resp))) + (rtc-db/remove-rtc-data-in-conn! (worker-state/get-current-repo)) + (worker-util/post-message :remote-graph-gone [])) (if-let [e ({:graph-not-exist r.ex/ex-remote-graph-not-exist :graph-not-ready r.ex/ex-remote-graph-not-ready :bad-request-body r.ex/ex-bad-request-body diff --git a/src/main/mobile/components/app.cljs b/src/main/mobile/components/app.cljs index 052ec465a8..bbf74043b6 100644 --- a/src/main/mobile/components/app.cljs +++ b/src/main/mobile/components/app.cljs @@ -4,11 +4,13 @@ [clojure.string :as string] [frontend.components.journal :as journal] [frontend.components.rtc.indicator :as rtc-indicator] + [frontend.config :as config] [frontend.date :as date] [frontend.db :as db] [frontend.db.conn :as db-conn] [frontend.handler.editor :as editor-handler] [frontend.handler.page :as page-handler] + [frontend.handler.repo :as repo-handler] [frontend.handler.user :as user-handler] [frontend.mobile.util :as mobile-util] [frontend.rum :as frum] @@ -35,10 +37,17 @@ [promesa.core :as p] [rum.core :as rum])) -(rum/defc app-graphs-select +(rum/defc app-graphs-select < rum/reactive [] (let [current-repo (state/get-current-repo) - graphs (state/get-repos) + graphs (->> (state/sub [:me :repos]) + (util/distinct-by :url)) + remote-graphs (state/sub :rtc/graphs) + graphs (->> + (if (seq remote-graphs) + (repo-handler/combine-local-&-remote-graphs graphs remote-graphs) + graphs) + (filter (fn [item] (config/db-based-graph? (:url item))))) short-repo-name (if current-repo (db-conn/get-short-repo-name current-repo) "Select a Graph")] @@ -49,9 +58,11 @@ :class "border-none w-full rounded-lg" :on-click (fn [] (let [buttons (concat - (for [repo graphs] - {:text (some-> (:url repo) (string/replace #"^logseq_db_" "")) - :role (:url repo)}) + (->> + (for [repo graphs] + {:text (some-> (:url repo) (string/replace #"^logseq_db_" "")) + :role (:url repo)}) + (remove (fn [{:keys [text]}] (string/blank? text)))) [{:text "Add new graph" :role "add-new-graph"}])] (ui-component/open-modal! "Switch graph" diff --git a/src/main/mobile/components/popup.cljs b/src/main/mobile/components/popup.cljs index dc9e17b87f..d1df40b77c 100644 --- a/src/main/mobile/components/popup.cljs +++ b/src/main/mobile/components/popup.cljs @@ -1,11 +1,8 @@ (ns mobile.components.popup "Mobile popup" (:require [dommy.core :as dom] - [frontend.db :as db] [frontend.handler.editor :as editor-handler] [frontend.state :as state] - [logseq.common.config :as common-config] - [logseq.db :as ldb] [logseq.shui.popup.core :as shui-popup] [logseq.shui.ui :as shui] [mobile.components.ui :as mobile-ui] @@ -85,10 +82,7 @@ :initialBreakpoint initial-breakpoint :onDidPresent (fn [] (when (= :ls-quick-add (:id opts)) - (when-let [add-page (ldb/get-built-in-page (db/get-db) common-config/quick-add-page-name)] - (when (:block/_parent add-page) - (let [block (last (ldb/sort-by-order (:block/_parent add-page)))] - (editor-handler/edit-block! block :max {:container-id :unknown-container})))))) + (editor-handler/quick-add-open-last-block!))) :breakpoints breakpoints :onDidDismiss (fn [] (mobile-state/set-popup! nil)