diff --git a/clj-e2e/dev/user.clj b/clj-e2e/dev/user.clj index ec02bac9fe..5a77adebfc 100644 --- a/clj-e2e/dev/user.clj +++ b/clj-e2e/dev/user.clj @@ -60,6 +60,11 @@ (->> (future (run-tests 'logseq.e2e.plugins-basic-test)) (swap! *futures assoc :plugins-test))) +(defn run-rtc-extra-test + [] + (->> (future (run-tests 'logseq.e2e.rtc-extra-test)) + (swap! *futures assoc :rtc-extra-test))) + (defn run-all-basic-test [] (run-tests 'logseq.e2e.commands-basic-test diff --git a/clj-e2e/src/logseq/e2e/rtc.clj b/clj-e2e/src/logseq/e2e/rtc.clj index 2c496f4adf..d12ef24839 100644 --- a/clj-e2e/src/logseq/e2e/rtc.clj +++ b/clj-e2e/src/logseq/e2e/rtc.clj @@ -33,6 +33,7 @@ (defn wait-tx-update-to [new-tx] + (assert (int? new-tx)) (loop [i 5] (when (zero? i) (throw (ex-info "wait-tx-update-to" {:update-to new-tx}))) (util/wait-timeout 1000) diff --git a/clj-e2e/test/logseq/e2e/rtc_extra_test.clj b/clj-e2e/test/logseq/e2e/rtc_extra_test.clj index b07eb2cfe1..6373e4b70c 100644 --- a/clj-e2e/test/logseq/e2e/rtc_extra_test.clj +++ b/clj-e2e/test/logseq/e2e/rtc_extra_test.clj @@ -2,26 +2,46 @@ (:require [clojure.test :refer [deftest testing is use-fixtures run-tests]] [com.climate.claypoole :as cp] + [logseq.e2e.block :as b] [logseq.e2e.fixtures :as fixtures :refer [*page1 *page2]] [logseq.e2e.graph :as graph] + [logseq.e2e.rtc :as rtc] [logseq.e2e.util :as util] [wally.main :as w] - [wally.repl :as repl] - [logseq.e2e.block :as b])) + [wally.repl :as repl])) -(use-fixtures :once fixtures/open-2-pages) +(def *graph-name (atom nil)) +(defn cleanup-fixture + [f] + (f) + (w/with-page @*page2 + (assert (some? @*graph-name)) + (graph/remove-remote-graph @*graph-name))) + +(use-fixtures :once + fixtures/open-2-pages + ;; cleanup-fixture + ) (defn- offline - [offline?] - (.setOffline (.context (w/get-page)) offline?)) - -(defn- wait-for-ops-synced [] - (w/wait-for "button.cloud.on.queuing" {:timeout 1000}) - (w/wait-for "button.cloud.on.idle" {:timeout 5000})) + (.setOffline (.context (w/get-page)) true)) + +(defn- online + [] + (.setOffline (.context (w/get-page)) false)) + +(defn- insert-task-blocks + [title-prefix] + (doseq [status ["Backlog" "Todo" "Doing" "In review" "Done" "Canceled"] + priority ["No priority" "Low" "Medium" "High" "Urgent"]] + (b/new-block (str title-prefix "-" status "-" priority)) + (util/input-command status) + (util/input-command priority))) (deftest rtc-extra-test (let [graph-name (str "rtc-extra-test-graph-" (.toEpochMilli (java.time.Instant/now)))] + (reset! *graph-name graph-name) (testing "open 2 app instances, add a rtc graph, check this graph available on other instance" (cp/prun! 2 @@ -33,15 +53,23 @@ (w/with-page @*page2 (graph/wait-for-remote-graph graph-name) (graph/switch-graph graph-name true))) - (testing "rtc-stop app1, update app2, then rtc-start on app1" - (w/with-page @*page1 - (offline true)) + (testing "rtc-stop app1, add some task blocks, then rtc-start on app1" + (let [*latest-remote-tx (atom nil)] + (w/with-page @*page1 + (offline)) + (w/with-page @*page2 + (let [{:keys [_local-tx remote-tx]} + (rtc/with-wait-tx-updated + (insert-task-blocks "t1"))] + (reset! *latest-remote-tx remote-tx)) + ;; TODO: more operations + (util/exit-edit)) + (w/with-page @*page1 + (online) + (rtc/wait-tx-update-to @*latest-remote-tx) + ;; TODO: check blocks exist + ))) + (testing "cleanup" (w/with-page @*page2 - (dotimes [_i 3] - (b/new-blocks (map #(str "b" %) (range 10))) - (wait-for-ops-synced)) - ;; TODO: more operations - (repl/pause) - ) - ) - )) + (assert (some? @*graph-name)) + (graph/remove-remote-graph @*graph-name))))) diff --git a/deps/db/src/logseq/db/frontend/schema.cljs b/deps/db/src/logseq/db/frontend/schema.cljs index daf826d256..3260587a98 100644 --- a/deps/db/src/logseq/db/frontend/schema.cljs +++ b/deps/db/src/logseq/db/frontend/schema.cljs @@ -37,7 +37,7 @@ (map (juxt :major :minor) [(parse-schema-version x) (parse-schema-version y)]))) -(def version (parse-schema-version "64.8")) +(def version (parse-schema-version "64.9")) (defn major-version "Return a number. diff --git a/deps/db/src/logseq/db/sqlite/create_graph.cljs b/deps/db/src/logseq/db/sqlite/create_graph.cljs index 08390987c4..b4fcc1e68f 100644 --- a/deps/db/src/logseq/db/sqlite/create_graph.cljs +++ b/deps/db/src/logseq/db/sqlite/create_graph.cljs @@ -201,7 +201,8 @@ (sqlite-util/kv :logseq.kv/graph-initial-schema-version db-schema/version) (sqlite-util/kv :logseq.kv/graph-created-at (common-util/time-ms)) ;; Empty property value used by db.type/ref properties - {:db/ident :logseq.property/empty-placeholder}] + {:db/ident :logseq.property/empty-placeholder + :block/uuid (common-uuid/gen-uuid :builtin-block-uuid :logseq.property/empty-placeholder)}] import-type (into (sqlite-util/import-tx import-type))) initial-files [{:block/uuid (common-uuid/gen-uuid :builtin-block-uuid "logseq/config.edn") diff --git a/src/main/frontend/commands.cljs b/src/main/frontend/commands.cljs index 1d424a03d7..55aae931fd 100644 --- a/src/main/frontend/commands.cljs +++ b/src/main/frontend/commands.cljs @@ -439,11 +439,10 @@ (println "draw file created, " path)) text)) "Draw a graph with Excalidraw"]) - (when (util/electron?) - ["Upload an asset" - [[:editor/click-hidden-file-input :id]] - "Upload file types like image, pdf, docx, etc.)" - :icon/upload]) + ["Upload an asset" + [[:editor/click-hidden-file-input :id]] + "Upload file types like image, pdf, docx, etc.)" + :icon/upload] ["Template" [[:editor/input command-trigger nil] [:editor/search-template]] "Insert a created template here" diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index 385f240f4a..b9a442b631 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -3047,7 +3047,6 @@ (block-content config block edit-input-id block-id *show-query?)))) (rum/defcs ^:large-vars/cleanup-todo block-content-or-editor < rum/reactive - (rum/local false ::hover?) [state config {:block/keys [uuid] :as block} {:keys [edit-input-id block-id edit? hide-block-refs-count? refs-count *hide-block-refs? *show-query?]}] (let [format (if (config/db-based-graph? (state/get-current-repo)) :markdown @@ -3084,7 +3083,10 @@ :format format} edit-input-id config))] - [:div.flex.flex-1.w-full.block-content-wrapper {:style {:display "flex"}} + [:div.flex.flex-1.w-full.block-content-wrapper + {:style {:display "flex"}} + (when-let [actions-cp (:page-title-actions-cp config)] + (actions-cp block)) (block-content-with-error config block edit-input-id block-id *show-query? editor-box) (when (and (not hide-block-refs-count?) @@ -3639,8 +3641,6 @@ [:div.flex.flex-col.w-full [:div.block-main-content.flex.flex-row.gap-2 - (when-let [actions-cp (:page-title-actions-cp config)] - (actions-cp block)) (when page-icon page-icon) diff --git a/src/main/frontend/components/block.css b/src/main/frontend/components/block.css index 81ea05d9a2..a02e1bfd80 100644 --- a/src/main/frontend/components/block.css +++ b/src/main/frontend/components/block.css @@ -524,10 +524,16 @@ } } -.block-main-content { +.ls-page-title-container .block-content-wrapper { + .ls-page-title-actions { + @apply absolute -top-4 opacity-0; + left: -2px; + } + &:hover { - & > .db-page-title-actions { + & > .ls-page-title-actions { @apply delay-300 transition-opacity opacity-100; + } } } diff --git a/src/main/frontend/components/container.cljs b/src/main/frontend/components/container.cljs index 90499ba362..f97c23c157 100644 --- a/src/main/frontend/components/container.cljs +++ b/src/main/frontend/components/container.cljs @@ -931,7 +931,11 @@ (defn- on-mouse-up [e] - (when-not (.closest (.-target e) ".block-control-wrap") + (when-not (or (.closest (.-target e) ".block-control-wrap") + (.closest (.-target e) "button") + (.closest (.-target e) "input") + (.closest (.-target e) "textarea") + (.closest (.-target e) "a")) (editor-handler/show-action-bar!))) (rum/defcs ^:large-vars/cleanup-todo root-container < rum/reactive diff --git a/src/main/frontend/components/page.cljs b/src/main/frontend/components/page.cljs index 3d096756e9..bd6dfba145 100644 --- a/src/main/frontend/components/page.cljs +++ b/src/main/frontend/components/page.cljs @@ -192,13 +192,13 @@ (rum/defcs page-blocks-cp < rum/reactive db-mixins/query {:will-mount (fn [state] (when-not (config/db-based-graph?) - (let [page-e (first (:rum/args state)) - page-name (:block/name page-e)] - (when (and page-name - (db/journal-page? page-name) - (>= (date/journal-title->int page-name) - (date/journal-title->int (date/today)))) - (state/pub-event! [:journal/insert-template page-name])))) + (let [page-e (first (:rum/args state)) + page-name (:block/name page-e)] + (when (and page-name + (db/journal-page? page-name) + (>= (date/journal-title->int page-name) + (date/journal-title->int (date/today)))) + (state/pub-event! [:journal/insert-template page-name])))) state)} [state block* {:keys [sidebar? whiteboard?] :as config}] (when-let [id (:db/id block*)] @@ -420,11 +420,11 @@ (rum/defc db-page-title-actions [page] - [:div.absolute.-top-4.left-0.opacity-0.db-page-title-actions + [:div.ls-page-title-actions [:div.flex.flex-row.items-center.gap-2 (when-not (:logseq.property/icon (db/entity (:db/id page))) (shui/button - {:variant :outline + {:variant :ghost :size :sm :class "px-2 py-0 h-6 text-xs text-muted-foreground" :on-click (fn [e] @@ -434,7 +434,7 @@ "Add icon")) (shui/button - {:variant :outline + {:variant :ghost :size :sm :class "px-2 py-0 h-6 text-xs text-muted-foreground" :on-click (fn [e] diff --git a/src/main/frontend/components/page.css b/src/main/frontend/components/page.css index 85b65d2e80..9e19a66f58 100644 --- a/src/main/frontend/components/page.css +++ b/src/main/frontend/components/page.css @@ -92,7 +92,7 @@ } } - .db-page-title-actions { + .ls-page-title-actions { &:has(button[data-popup-active]) { @apply opacity-100; } diff --git a/src/main/frontend/components/property/value.cljs b/src/main/frontend/components/property/value.cljs index cd5f6c1043..0f68381f86 100644 --- a/src/main/frontend/components/property/value.cljs +++ b/src/main/frontend/components/property/value.cljs @@ -1156,7 +1156,7 @@ (if editing? (popup-content nil) (let [show! (fn [e] - (util/stop e) + (state/clear-selection!) (let [target (when e (.-target e))] (when-not (or config/publishing? (util/shift-key? e) @@ -1171,7 +1171,7 @@ {:ref *el :id trigger-id :tabIndex 0 - :on-click show! + :on-pointer-down show! :on-key-down (fn [e] (case (util/ekey e) ("Backspace" "Delete") diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index 1b015f647f..1bcd487f12 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -2,6 +2,7 @@ (:require [clojure.set :as set] [clojure.string :as string] [clojure.walk :as w] + [dommy.core :as d] [dommy.core :as dom] [electron.ipc :as ipc] [frontend.commands :as commands] @@ -1242,15 +1243,20 @@ (defonce *action-bar-timeout (atom nil)) +(defn popup-exists? + [id] + (some->> (shui-popup/get-popups) + (some #(some-> % (:id) (str) (string/includes? (str id)))))) + (defn show-action-bar! [& {:keys [delay] :or {delay 200}}] - (when (config/db-based-graph?) + (when (and (config/db-based-graph?) (not (popup-exists? :selection-action-bar))) (when-let [timeout @*action-bar-timeout] (js/clearTimeout timeout)) (state/pub-event! [:editor/hide-action-bar]) - - (when (seq (state/get-selection-blocks)) + (when (seq (remove (fn [b] (d/has-class? b "ls-table-cell")) + (state/get-selection-blocks))) (let [timeout (js/setTimeout #(state/pub-event! [:editor/show-action-bar]) delay)] (reset! *action-bar-timeout timeout))))) @@ -3325,11 +3331,6 @@ (cursor/select-up-down input direction anchor cursor-rect))) (select-block-up-down direction)))) -(defn popup-exists? - [id] - (some->> (shui-popup/get-popups) - (some #(some-> % (:id) (str) (string/includes? (str id)))))) - (defn editor-commands-popup-exists? [] (popup-exists? "editor.commands")) diff --git a/src/main/frontend/util.cljc b/src/main/frontend/util.cljc index 7a3aef697e..868d85bb7d 100644 --- a/src/main/frontend/util.cljc +++ b/src/main/frontend/util.cljc @@ -790,6 +790,11 @@ (->> blocks (remove (fn [b] (= "true" (d/attr b "data-embed"))))))) +#?(:cljs + (defn remove-property-value-blocks [blocks] + (->> blocks + (remove (fn [b] (d/has-class? b "property-value-container")))))) + #?(:cljs (defn get-selected-text [] @@ -898,7 +903,8 @@ (defn get-prev-block-non-collapsed-non-embed [block] (when-let [blocks (->> (get-blocks-noncollapse) - remove-embedded-blocks)] + remove-embedded-blocks + remove-property-value-blocks)] (when-let [index (.indexOf blocks block)] (let [idx (dec index)] (when (>= idx 0) diff --git a/src/main/frontend/worker/db/migrate.cljs b/src/main/frontend/worker/db/migrate.cljs index d81a866a5c..2a6fd9519c 100644 --- a/src/main/frontend/worker/db/migrate.cljs +++ b/src/main/frontend/worker/db/migrate.cljs @@ -859,6 +859,12 @@ :logseq.task/scheduled :logseq.property/scheduled}) conn search-db)) + +(defn- empty-placeholder-add-block-uuid + [_conn _search-db] + [{:db/ident :logseq.property/empty-placeholder + :block/uuid (common-uuid/gen-uuid :builtin-block-uuid :logseq.property/empty-placeholder)}]) + (def ^:large-vars/cleanup-todo schema-version->updates "A vec of tuples defining datascript migrations. Each tuple consists of the schema version integer and a migration map. A migration map can have keys of :properties, :classes @@ -958,8 +964,8 @@ [62 {:fix remove-block-schema}] [63 {:properties [:logseq.property.table/pinned-columns]}] [64 {:fix update-view-filter}] - ;;;; schema-version format: "." - ;;;; int number equals to "" (without ) +;;;; schema-version format: "." +;;;; int number equals to "" (without ) ["64.1" {:properties [:logseq.property.view/group-by-property] :fix add-view-icons}] ["64.2" {:properties [:logseq.property.view/feature-type] @@ -970,7 +976,8 @@ ["64.5" {:fix add-group-by-property-for-list-views}] ["64.6" {:fix cardinality-one-multiple-values}] ["64.7" {:fix rename-repeated-properties}] - ["64.8" {:fix rename-task-properties}]]) + ["64.8" {:fix rename-task-properties}] + ["64.9" {:fix empty-placeholder-add-block-uuid}]]) (let [[major minor] (last (sort (map (comp (juxt :major :minor) db-schema/parse-schema-version first) schema-version->updates)))