Merge branch 'feat/db' into feat/capacitor-new

This commit is contained in:
charlie
2025-04-25 10:36:05 +08:00
45 changed files with 987 additions and 834 deletions

View File

@@ -8,7 +8,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 84
versionName "0.10.10"
versionName "0.11.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

View File

@@ -0,0 +1,3 @@
{:linters
{:unresolved-var {:exclude [wally.main/click
wally.main/fill]}}}

4
clj-e2e/.cljfmt.edn Normal file
View File

@@ -0,0 +1,4 @@
{:extra-indents {missionary.core/sp [[:block 0]]
missionary.core/ap [[:block 0]]
frontend.common.missionary/run-task [[:inner 0]]}
:sort-ns-references? true}

View File

@@ -18,4 +18,5 @@
-dev {:depends [serve prn test]}
dev {:task (run '-dev {:parallel true})}}}
dev {:doc "serve and test"
:task (run '-dev {:parallel true})}}}

View File

@@ -4,7 +4,7 @@
io.github.pfeodrippe/wally {:git/url "https://github.com/logseq/wally"
:sha "6b0583701fc64ec5177eec6577e33bb8d9115d61"}
;; io.github.zmedelis/bosquet {:mvn/version "2025.03.28"}
}
org.clj-commons/claypoole {:mvn/version "1.2.2"}}
:aliases
{:build {:deps {io.github.clojure/tools.build {:mvn/version "0.10.5"}}
:ns-default build}

View File

@@ -0,0 +1,12 @@
(ns logseq.e2e.keyboard
(:require [wally.main :as w]))
(def press w/keyboard-press)
(def enter #(press "Enter"))
(def esc #(press "Escape"))
(def backspace #(press "Backspace"))
(def tab #(press "Tab"))
(def shift+tab #(press "Shift+Tab"))
(def arrow-up #(press "ArrowUp"))
(def arrow-down #(press "ArrowDown"))

View File

@@ -3,8 +3,10 @@
(:require [clojure.string :as string]
[clojure.test :refer [is]]
[wally.main :as w]
[wally.selectors :as ws])
(:import (com.microsoft.playwright.assertions PlaywrightAssertions)))
[wally.selectors :as ws]
[logseq.e2e.keyboard :as k])
(:import [com.microsoft.playwright TimeoutError]
[com.microsoft.playwright.assertions PlaywrightAssertions]))
(def assert-that PlaywrightAssertions/assertThat)
@@ -37,8 +39,6 @@
(let [input-node (w/-query "*:focus")]
(.type input-node text)))
(def press w/keyboard-press)
(defn search
[text]
(w/click :#search-button)
@@ -67,7 +67,7 @@
(defn new-block
[title]
(press "Enter")
(k/enter)
(input title))
(defn save-block
@@ -76,14 +76,14 @@
(defn exit-edit
[]
(press "Escape"))
(k/esc))
(defn delete-blocks
"Delete the current block if in editing mode, otherwise, delete all the selected blocks."
[]
(let [editor (get-editor)]
(when editor (exit-edit))
(press "Backspace")))
(k/backspace)))
(defn get-text
[locator]
@@ -117,7 +117,7 @@
[indent?]
(let [editor (get-editor)
[x1 _] (bounding-xy editor)
_ (press (if indent? "Tab" "Shift+Tab"))
_ (if indent? (k/tab) (k/shift+tab))
[x2 _] (bounding-xy editor)]
(if indent?
(is (< x1 x2))
@@ -138,7 +138,7 @@
(defn repeat-keyboard
[n shortcut]
(dotimes [_i n]
(press shortcut)))
(k/press shortcut)))
(defn get-page-blocks-contents
[]
@@ -146,4 +146,46 @@
(def mac? (= "Mac OS X" (System/getProperty "os.name")))
(def mod-key (if mac? "Meta" "Control"))
(defn login-test-account
[& {:keys [username password]
:or {username "e2etest"
password "Logseq-e2e"}}]
(w/eval-js "localStorage.setItem(\"login-enabled\",true);")
(w/click "button[title=\"More\"]")
(w/click "div:text(\"Login\")")
(input username)
(k/tab)
(input password)
(w/click "button[type=\"submit\"]:text(\"Sign in\")")
(w/wait-for-not-visible ".cp__user-login"))
(defn new-graph
[graph-name enable-sync?]
(search "add a db graph")
(w/click (w/get-by-label "Add a DB graph"))
(w/wait-for "h2:text(\"Create a new graph\")")
(w/click "input[placeholder=\"your graph name\"]")
(input graph-name)
(when enable-sync?
(w/click "button#rtc-sync"))
(w/click "button:text(\"Submit\")")
(when enable-sync?
(w/wait-for "button.cloud.on.idle" {:timeout 20000})))
(defn wait-for-remote-graph
[graph-name]
(search "all graphs")
(w/click (w/get-by-label "Go to all graphs"))
(let [max-try 5]
(loop [i 0]
(prn :wait-for-remote-graph-try i)
(w/click "span:text(\"Refresh\")")
(let [succ?
(try
(w/wait-for (str "span:has-text(\"" graph-name "\")"))
true
(catch TimeoutError e
(if (= max-try i)
(throw e)
false)))]
(when-not succ? (recur (inc i)))))))

View File

@@ -3,7 +3,8 @@
[clojure.string :as string]
[clojure.test :refer [deftest testing is use-fixtures]]
[logseq.e2e.fixtures :as fixtures]
[logseq.e2e.util :as util :refer [press]]
[logseq.e2e.keyboard :as k]
[logseq.e2e.util :as util]
[wally.main :as w]))
(use-fixtures :once fixtures/open-page)
@@ -15,7 +16,7 @@
(util/type " /")
(w/wait-for ".ui__popover-content")
(is (some? (w/find-one-by-text "span" "Node reference")))
(press "Backspace")
(k/backspace)
(w/wait-for-not-visible ".ui__popover-content"))
(testing "Node reference"
@@ -23,9 +24,9 @@
(util/new-block "/")
(util/type "Node eferen")
(w/wait-for ".ui__popover-content")
(press "Enter")
(k/enter)
(util/type "Another page")
(press "Enter")
(k/enter)
(is (= "[[Another page]]" (util/get-edit-content)))
(util/exit-edit)
(is (= "Another page" (util/get-text "a.page-ref"))))
@@ -33,10 +34,10 @@
(util/new-block "/")
(util/type "Node eferen")
(w/wait-for ".ui__popover-content")
(press "Enter")
(k/enter)
(util/type "b1")
(util/wait-timeout 300)
(press "Enter")
(k/enter)
(is (string/includes? (util/get-edit-content) "[["))
(util/exit-edit)
(is (= "b1" (util/get-text ".block-ref"))))))

View File

@@ -4,8 +4,9 @@
;; TODO: save trace
;; TODO: parallel support
(defn open-page
[f & {:keys [headless]
:or {headless true}}]
[f & {:keys [headless port]
:or {headless true
port 3002}}]
(w/with-page-open
(w/make-page {:headless headless
:persistent false
@@ -13,5 +14,31 @@
;; Set `slow-mo` lower to find more flaky tests
;; :slow-mo 30
})
(w/navigate "http://localhost:3002")
(w/navigate (str "http://localhost:" port))
(f)))
(def *page1 (atom nil))
(def *page2 (atom nil))
(defn open-2-pages
"Use `*page1` and `*page2` in `f`"
[f & {:keys [headless port]
:or {headless true
port 3002}}]
(let [p1 (w/make-page {:headless headless
:persistent false
:slow-mo 100})
p2 (w/make-page {:headless headless
:persistent false
:slow-mo 100})]
(run!
#(w/with-page %
(w/navigate (str "http://localhost:" port)))
[p1 p2])
(reset! *page1 p1)
(reset! *page2 p2)
(binding [w/*page* (delay (throw (ex-info "Don't use *page*, use *page1* and *page2* instead" {})))]
(f))
(w/with-page-open p1)
(w/with-page-open p2)))

View File

@@ -2,7 +2,8 @@
(:require
[clojure.test :refer [deftest testing is use-fixtures]]
[logseq.e2e.fixtures :as fixtures]
[logseq.e2e.util :as util :refer [press]]
[logseq.e2e.keyboard :as k]
[logseq.e2e.util :as util]
[wally.main :as w]))
(use-fixtures :once fixtures/open-page)
@@ -25,7 +26,7 @@
(testing "indent a block with its children"
(util/new-block "b3")
(util/indent)
(press "ArrowUp")
(k/arrow-up)
(util/indent)
(util/exit-edit)
(let [[x1 x2 x3] (map (comp first util/bounding-xy #(w/find-one-by-text "span" %)) ["b1" "b2" "b3"])]
@@ -35,7 +36,7 @@
(util/open-last-block)
(util/new-blocks ["b4" "b5"])
(util/indent)
(util/press "ArrowUp")
(k/arrow-up)
(util/outdent)
(util/exit-edit)
(let [[x2 x3 x4 x5] (map (comp first util/bounding-xy #(w/find-one-by-text "span" %)) ["b2" "b3" "b4" "b5"])]
@@ -68,9 +69,9 @@
(util/new-page "p5")
(util/new-blocks ["b1" "b2" "b3" "b4"])
(util/indent)
(press "ArrowUp")
(k/arrow-up)
(util/indent)
(press "ArrowUp")
(k/arrow-up)
(util/delete-blocks)
(is (= "b1" (util/get-edit-content)))
(is (= 1 (util/page-blocks-count)))))

View File

@@ -0,0 +1,29 @@
(ns logseq.e2e.rtc-basic-test
(:require
[clojure.test :refer [deftest testing is use-fixtures]]
[com.climate.claypoole :as cp]
[logseq.e2e.fixtures :as fixtures :refer [*page1 *page2]]
[logseq.e2e.util :as util]
[wally.main :as w]
[wally.repl :as repl]))
(use-fixtures :once fixtures/open-2-pages)
;; (use-fixtures :once #(fixtures/open-2-pages % :headless false :port 3001))
(deftest rtc-basic-test
(let [graph-name (str "rtc-graph-" (.toEpochMilli (java.time.Instant/now)))]
(testing "open 2 app instances"
(cp/prun!
2
#(w/with-page %
(util/login-test-account))
[@*page1 @*page2])
(w/with-page @*page1
(util/new-graph graph-name true))
(w/with-page @*page2
(util/wait-for-remote-graph graph-name)))))
(comment
(def xxx (future (clojure.test/run-tests)))
(future-cancel xxx))

View File

@@ -3,7 +3,7 @@
"version": "1.0.0",
"private": true,
"devDependencies": {
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19"
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20"
},
"scripts": {
"test": "yarn nbb-logseq -cp test -m nextjournal.test-runner"

View File

@@ -2,9 +2,9 @@
# yarn lockfile v1
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
version "1.2.173-feat-db-v19"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
version "1.2.173-feat-db-v20"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
dependencies:
import-meta-resolve "^2.1.0"

View File

@@ -3,7 +3,7 @@
"version": "1.0.0",
"private": true,
"devDependencies": {
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19"
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20"
},
"dependencies": {
"better-sqlite3": "9.3.0"

View File

@@ -159,8 +159,7 @@
(assoc :db/id (:db/id entity))))
(defn ^:large-vars/cleanup-todo get-block-and-children
[db id {:keys [children? children-only? nested-children? including-property-vals? properties children-props]
:or {including-property-vals? true}}]
[db id {:keys [children? children-only? nested-children? properties children-props]}]
(let [block (d/entity db (if (uuid? id)
[:block/uuid id]
id))
@@ -205,7 +204,7 @@
(entity->map block))
block' (cond->
(mark-block-fully-loaded block')
including-property-vals?
true
(update-vals (fn [v]
(cond
(de/entity? v)

View File

@@ -94,7 +94,8 @@
[db {:keys [id asc?] :as sorting} entities partition?]
(let [property (or (d/entity db id) {:db/ident id})
get-value-fn (memoize (get-value-for-sort property))
sorted-entities (cond
sorted-entities (->>
(cond
(= id :block.temp/refs-count)
(cond-> (sort-by :block.temp/refs-count entities)
(not asc?)
@@ -121,7 +122,8 @@
(fn [d]
(when (row-ids (:e d))
(id->row (:e d))))
datoms)))))]
datoms)))))
distinct)]
(if partition?
(partition-by get-value-fn sorted-entities)
sorted-entities)))
@@ -339,7 +341,7 @@
(let [e (d/entity db eid)]
(when-not (or (some #(= id %) (map :db/id (:block/refs e)))
(:block/link e)
(ldb/page? e))
(ldb/built-in? e))
e)))
ids)))))
@@ -563,6 +565,6 @@
(map :db/id result))]
(cond->
{:count (count filtered-entities)
:data data'}
:data (distinct data')}
(= feat-type :linked-references)
(assoc :ref-pages-count (:ref-pages-count entities-result))))))

6
deps/db/yarn.lock vendored
View File

@@ -2,9 +2,9 @@
# yarn lockfile v1
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
version "1.2.173-feat-db-v19"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
version "1.2.173-feat-db-v20"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
dependencies:
import-meta-resolve "^2.1.0"

View File

@@ -3,7 +3,7 @@
"version": "1.0.0",
"private": true,
"devDependencies": {
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19",
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20",
"better-sqlite3": "9.3.0"
},
"dependencies": {

View File

@@ -2,9 +2,9 @@
# yarn lockfile v1
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
version "1.2.173-feat-db-v19"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
version "1.2.173-feat-db-v20"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
dependencies:
import-meta-resolve "^2.1.0"

View File

@@ -3,7 +3,7 @@
"version": "1.0.0",
"private": true,
"devDependencies": {
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19"
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20"
},
"dependencies": {
"better-sqlite3": "9.3.0",

View File

@@ -2,9 +2,9 @@
# yarn lockfile v1
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
version "1.2.173-feat-db-v19"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
version "1.2.173-feat-db-v20"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
dependencies:
import-meta-resolve "^2.1.0"

View File

@@ -3,7 +3,7 @@
"version": "1.0.0",
"private": true,
"devDependencies": {
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19",
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20",
"mldoc": "^1.5.9"
},
"dependencies": {

View File

@@ -2,9 +2,9 @@
# yarn lockfile v1
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
version "1.2.173-feat-db-v19"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
version "1.2.173-feat-db-v20"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
dependencies:
import-meta-resolve "^2.1.0"

View File

@@ -519,7 +519,7 @@
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 0.10.10;
MARKETING_VERSION = 0.11.0;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -546,7 +546,7 @@
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 0.10.10;
MARKETING_VERSION = 0.11.0;
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
@@ -571,7 +571,7 @@
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 0.10.10;
MARKETING_VERSION = 0.11.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
@@ -598,7 +598,7 @@
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 0.10.10;
MARKETING_VERSION = 0.11.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -1,7 +1,7 @@
{
"name": "Logseq",
"productName": "Logseq",
"version": "0.10.10",
"version": "0.11.0",
"main": "electron.js",
"author": "Logseq",
"license": "AGPL-3.0",

View File

@@ -3,7 +3,7 @@
"version": "1.0.0",
"private": true,
"devDependencies": {
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v19"
"@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v20"
},
"dependencies": {
"better-sqlite3": "9.3.0",

View File

@@ -2,9 +2,9 @@
# yarn lockfile v1
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v19":
version "1.2.173-feat-db-v19"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/ca32553da41aff783d89264b2e1a753372721f2e"
"@logseq/nbb-logseq@logseq/nbb-logseq#feat-db-v20":
version "1.2.173-feat-db-v20"
resolved "https://codeload.github.com/logseq/nbb-logseq/tar.gz/7fb63423ab566717cac79e5f76084d89b845fbd6"
dependencies:
import-meta-resolve "^2.1.0"

View File

@@ -507,14 +507,7 @@
(file-based-asset-loader @src
#(resizable-image config title @src metadata full_text true)))
(and db-based? (contains? (common-config/text-formats) ext) (:asset-block config))
(let [file-name (str (:block/title (:asset-block config)) "." (name ext))]
[:a.asset-ref.is-plaintext
{:href @src
:download file-name}
file-name])
(contains? (common-config/text-formats) ext)
(and (not db-based?) (contains? (common-config/text-formats) ext))
[:a.asset-ref.is-plaintext {:href (rfe/href :file {:path path})
:on-click (fn [_event]
(p/let [result (fs/read-file repo-dir path)]
@@ -534,8 +527,15 @@
title
[:span [:span.opacity-70 "[[📚"] title [:span.opacity-70 "]]"]])]
db-based?
(let [file-name (str (:block/title (:asset-block config)) "." (name ext))]
[:a.asset-ref.is-plaintext
{:href @src
:download file-name}
file-name])
:else
[:a.asset-ref.is-doc {:href @src
[:a.asset-ref {:href @src
:on-click share-fn}
title])))))
@@ -926,8 +926,7 @@
(reset! *result page)
:else
(p/let [result (db-async/<get-block (state/get-current-repo) page-id-or-name {:children? false
:skip-refresh? true
:including-property-vals? false})]
:skip-refresh? true})]
(reset! *result result)))
(assoc state :*entity *result)))}
@@ -1003,7 +1002,6 @@
(->elem :span (map-inline config title))
:else
path)]
[:div.asset-ref-wrap
{:data-ext ext-name}
@@ -3675,7 +3673,7 @@
(when-not (or in-whiteboard? table? property?) (dnd-separator-wrapper block children block-id slide? false false))]))
(rum/defc ^:large-vars/cleanup-todo block-container-inner
(rum/defc block-container-inner
[container-state repo config* block opts]
(let [container-id (:container-id config*)
block-id (:block/uuid block)

View File

@@ -40,7 +40,7 @@
highlighted-text (string/replace normal-text query-re "<:hlmarker>$1<:hlmarker>")
segs (string/split highlighted-text #"<:hlmarker>")]
(if (seq segs)
(into [:span]
(into [:span {:aria-label text-string}]
(map-indexed (fn [i seg]
(if (even? i)
[:span seg]

View File

@@ -86,7 +86,6 @@
[page icon recent?]
(let [repo (state/get-current-repo)
db-based? (config/db-based-graph? repo)
page (or (db/get-alias-source-page repo (:db/id page)) page)
title (:block/title page)
untitled? (db-model/untitled-page? title)
name (:block/name page)

View File

@@ -354,7 +354,7 @@
[matched-templates set-matched-templates!] (rum/use-state nil)]
(hooks/use-effect! (fn []
(p/let [result (editor-handler/<get-matched-templates q)]
(set-matched-templates! result)))
(set-matched-templates! (sort-by :block/title result))))
[q])
(ui/auto-complete
matched-templates

View File

@@ -331,10 +331,9 @@
(when (state/sub :ui/toggle-highlight-recent-blocks?)
(recent-slider-inner)))
(rum/defc ^:large-vars/cleanup-todo header < rum/reactive
(rum/defc ^:large-vars/cleanup-todo header-aux < rum/reactive
[{:keys [current-repo default-home new-block-mode]}]
(let [_ (state/sub [:user/info :UserGroups])
electron-mac? (and util/mac? (util/electron?))
(let [electron-mac? (and util/mac? (util/electron?))
left-menu (left-menu-button {:on-click (fn []
(state/set-left-sidebar-open!
(not (:ui/left-sidebar-open? @state/state))))})
@@ -421,3 +420,15 @@
(sidebar/toggle)
(updater-tips-new-version t)]]))
(def ^:private header-related-flow
(m/latest
(fn [state rtc-running?]
{:user-groups (get-in state [:user/info :UserGroups])
:rtc-running? rtc-running?})
(m/watch state/state) rtc-flows/rtc-running-flow))
(rum/defc header
[opts]
(let [_m (hooks/use-flow-state header-related-flow)]
(header-aux opts)))

View File

@@ -610,6 +610,11 @@
clear-value-label [:div.flex.flex-row.items-center.gap-1.text-sm
(ui/icon "x" {:size 14})
[:div clear-value]]
items (if (:property/closed-values property)
items ; sorted by order
(sort-by (fn [item]
(db-property/property-value-content item))
items))
items' (->>
(if (and (seq selected-choices)
(not multiple-choices?)
@@ -655,10 +660,9 @@
(rum/defc ^:large-vars/cleanup-todo select-node < rum/static
[property
{:keys [block multiple-choices? dropdown? input-opts on-input] :as opts}
{:keys [block multiple-choices? dropdown? input-opts on-input add-new-choice!] :as opts}
result]
(let [[refresh-count set-refresh-count!] (rum/use-state 0)
repo (state/get-current-repo)
(let [repo (state/get-current-repo)
classes (:logseq.property/classes property)
tags? (= :block/tags (:db/ident property))
alias? (= :block/alias (:db/ident property))
@@ -772,8 +776,9 @@
(str "Set " (:block/title property)))
:show-new-when-not-exact-match? (if (or (and parent-property? (contains? (set children-pages) (:db/id block)))
;; Don't allow creating private tags
(and (= :block/tags (:db/ident property))
(seq (set/intersection (set (map :db/ident classes'))
ldb/private-tags)))
ldb/private-tags))))
false
true)
:extract-chosen-fn :value
@@ -781,18 +786,21 @@
:input-opts input-opts
:on-input (debounce on-input 50)
:on-chosen (fn [chosen selected?]
(p/let [[id new?] (if (integer? chosen)
[chosen false]
(p/let [id (if (integer? chosen)
chosen
(when-not (string/blank? (string/trim chosen))
(p/let [result (<create-page-if-not-exists! block property classes' chosen)]
[result true])))
(<create-page-if-not-exists! block property classes' chosen)))
_ (when (and (integer? id) (not (entity-util/page? (db/entity id))))
(db-async/<get-block repo id))]
(p/do!
(if id
(p/do!
(add-or-remove-property-value block property id selected? {})
(log/error :msg "No :db/id found or created for chosen" :chosen chosen))
(when new? (set-refresh-count! (inc refresh-count))))))})
(when (fn? add-new-choice!)
(add-new-choice!
(let [e (db/entity id)]
{:value (select-keys e [:db/id :block/uuid])
:label (:block/title e)}))))
(log/error :msg "No :db/id found or created for chosen" :chosen chosen))))})
(and (seq classes') (not tags-or-alias?))
(assoc
@@ -834,11 +842,13 @@
:input-opts input-opts
:on-input (fn [v]
(if (string/blank? v)
initial-choices
(set-result! initial-choices)
;; TODO rank initial choices higher
(p/let [result (search/block-search (state/get-current-repo) v {:enable-snippet? false
:built-in? false})]
(set-result! result)))))
(set-result! result))))
:add-new-choice! (fn [new-choice]
(set-initial-choices! (conj (vec initial-choices) new-choice))))
repo (state/get-current-repo)
classes (:logseq.property/classes property)
class? (= :class (:logseq.property/type property))
@@ -1081,7 +1091,7 @@
(contains? #{:node :class :property :page} type)
(when-let [reference (state/get-component :block/reference)]
(reference {:table-view? table-view?} (:block/uuid value)))
(when value (reference {:table-view? table-view?} (:block/uuid value))))
(and (map? value) (some? (db-property/property-value-content value)))
(let [content (str (db-property/property-value-content value))]
@@ -1338,11 +1348,14 @@
self-value-or-embedded? (fn [v]
(or (= (:db/id v) (:db/id block))
;; property value self embedded
(= (:db/id (:block/link v)) (:db/id block))))]
(if (and (or (and (entity-map? v) (self-value-or-embedded? v))
(and (:db/id block) (= (:db/id (:block/link v)) (:db/id block)))))]
(if (and (or (and (entity-map? v)
(self-value-or-embedded? v))
(and (coll? v) (every? entity-map? v)
(some self-value-or-embedded? v))
(and (= p-block (:db/id block)) (= p-property (:db/id property))))
(and (:db/id block)
(= p-block (:db/id block))
(= p-property (:db/id property))))
(not= :logseq.class/Tag (:db/ident block)))
[:div.flex.flex-row.items-center.gap-1
[:div.warning "Self reference"]

View File

@@ -51,7 +51,7 @@
:local-tx (:local-tx state)
:remote-tx (:remote-tx state)
:rtc-state (if (:rtc-lock state) :open :close)))
rtc-flows/rtc-state-stream-flow)))]
rtc-flows/rtc-state-flow)))]
(reset! *update-detail-info-canceler canceler))))
(run-task--update-detail-info)

View File

@@ -52,6 +52,13 @@
(reset! *input input)
(when (fn? on-input) (on-input input)))
[(hooks/use-debounced-value input 100)])
(hooks/use-effect!
(fn []
(when (= "" @*input)
(set-input! "")))
[(hooks/use-debounced-value @*input 100)])
[:div.input-wrap
{:style {:margin-bottom "-2px"}}
[:input.cp__select-input.w-full
@@ -65,6 +72,7 @@
(set-input! v)))}
input-opts)]]))
;; TODO: rewrite using hooks
(rum/defcs ^:large-vars/cleanup-todo select
"Provides a select dropdown powered by a fuzzy search. Takes the following options:
* :items - Vec of things to select from. Assumes a vec of maps with :value key by default. Required option
@@ -83,8 +91,8 @@
(rum/local "" ::input)
(rum/local nil ::toggle)
{:init (fn [state]
(assoc state ::selected-choices
(atom (set (:selected-choices (first (:rum/args state)))))))
(let [choices (:selected-choices (first (:rum/args state)))]
(assoc state ::selected-choices (atom (set choices)))))
:will-remount (fn [_old-state new-state]
(let [choices (set (:selected-choices (first (:rum/args new-state))))]
(when (not= choices @(::selected-choices new-state))
@@ -113,9 +121,7 @@
*selected-choices (::selected-choices state)
selected-choices (rum/react *selected-choices)
full-choices (cond->>
(->> (concat (map (fn [v] {:value v}) selected-choices) items)
(util/distinct-by-last-wins :value)
(remove nil?))
(remove nil? items)
(seq @input)
(remove :clear?))
search-result' (->>
@@ -126,7 +132,7 @@
exact-transform-fn (if new-case-sensitive? identity string/lower-case)
exact-match? (contains? (set (map (comp exact-transform-fn str extract-fn) search-result'))
(exact-transform-fn @input))
search-result' (if multiple-choices?
search-result' (if (and multiple-choices? (not (string/blank? @input)))
(sort-by (fn [item]
(not (contains? selected-choices (:value item))))
search-result')

View File

@@ -600,11 +600,11 @@
(not instrument-disabled?)))
[:span.text-sm.opacity-50 (t :settings-page/disable-sentry-desc)]))
(defn clear-cache-row [t]
(row-with-button-action {:left-label (t :settings-page/clear-cache)
:button-label (t :settings-page/clear)
:on-click #(state/pub-event! [:graph/clear-cache!])
:-for "clear_cache"}))
;; (defn clear-cache-row [t]
;; (row-with-button-action {:left-label (t :settings-page/clear-cache)
;; :button-label (t :settings-page/clear)
;; :on-click #(state/pub-event! [:graph/clear-cache!])
;; :-for "clear_cache"}))
(defn version-row [t version]
(row-with-button-action {:left-label (t :settings-page/current-version)
@@ -823,11 +823,12 @@
(when-not (mobile-util/native-platform?) (developer-mode-row t developer-mode?))
(when (util/electron?) (https-user-agent-row https-agent-opts))
(when (util/electron?) (auto-chmod-row t))
(clear-cache-row t)
;; (clear-cache-row t)
(ui/admonition
:warning
[:p (t :settings-page/clear-cache-warning)])]))
;; (ui/admonition
;; :warning
;; [:p (t :settings-page/clear-cache-warning)])
]))
(rum/defc sync-enabled-switcher
[enabled?]

View File

@@ -1224,8 +1224,7 @@
db-id (cond (map? item) (:db/id item)
(number? item) item
:else nil)
block (some-> db-id db/entity)
[item set-item!] (hooks/use-state (when (:block.temp/fully-loaded? block) block))
[item set-item!] (hooks/use-state nil)
opts (if list-view?
{:skip-refresh? true
:children? false}
@@ -1826,6 +1825,7 @@
(hooks/use-debounced-value input 300)
sorting-filters
(:db/id (:logseq.property.view/group-by-property view-entity))
(:db/id (:logseq.property.view/type view-entity))
;; page filters
(:logseq.property.linked-references/includes view-parent)
(:logseq.property.linked-references/excludes view-parent)

View File

@@ -15,6 +15,7 @@
[frontend.handler.file-based.property.util :as property-util]
[frontend.state :as state]
[frontend.util :as util]
[logseq.common.util :as common-util]
[logseq.db :as ldb]
[logseq.db.frontend.property :as db-property]
[promesa.core :as p]))
@@ -126,6 +127,7 @@
(p/promise e)
:else
(->
(p/let [result (state/<invoke-db-worker :thread-api/get-blocks graph
[{:id id :opts opts}])
{:keys [block children]} (first result)]
@@ -133,12 +135,17 @@
(let [conn (db/get-db graph false)
block-and-children (if block (cons block children) children)
affected-keys [[:frontend.worker.react/block (:db/id block)]]
tx-data (remove (fn [b] (:block.temp/fully-loaded? (db/entity (:db/id b)))) block-and-children)]
tx-data (->> (remove (fn [b] (:block.temp/fully-loaded? (db/entity (:db/id b)))) block-and-children)
(common-util/fast-remove-nils)
(remove empty?))]
(when (seq tx-data) (d/transact! conn tx-data))
(when-not skip-refresh?
(react/refresh-affected-queries! graph affected-keys))))
(if children-only? children block)))))
(if children-only? children block))
(p/catch (fn [error]
(js/console.error error)
(throw (ex-info "get-block error" {:block id-uuid-or-name}))))))))
(defn <get-blocks
[graph ids* & {:as opts}]

View File

@@ -28,8 +28,8 @@
(def rtc-state-flow
(m/watch (:rtc/state @state/state)))
(def rtc-state-stream-flow
(m/stream rtc-state-flow))
(def rtc-running-flow
(m/eduction (map :rtc-lock) rtc-state-flow))
(def rtc-online-users-flow
(c.m/throttle
@@ -40,7 +40,7 @@
(:rtc-lock m))
(:online-users m))))
(dedupe)
rtc-state-stream-flow)))
rtc-state-flow)))
(def ^:private network-online-change-flow
(m/stream
@@ -64,7 +64,7 @@ conditions:
(->> (m/latest
(fn [rtc-state _ login-user]
(assoc rtc-state :login-user login-user))
(c.m/continue-flow rtc-state-stream-flow)
rtc-state-flow
(c.m/continue-flow network-online-change-flow)
flows/current-login-user-flow)
(m/eduction

View File

@@ -3568,10 +3568,11 @@
[block]
(let [class-properties (:classes-properties (outliner-property/get-block-classes-properties (db/get-db) (:db/id block)))
db (db/get-db)
attributes (set (remove #{:block/alias} db-property/db-attribute-properties))
properties (->> (:block.temp/property-keys block)
(map (partial entity-plus/entity-memoized db))
(concat class-properties)
(remove (fn [e] (db-property/db-attribute-properties (:db/ident e))))
(remove (fn [e] (attributes (:db/ident e))))
(remove outliner-property/property-with-other-position?)
(remove (fn [e] (:logseq.property/hide? e)))
(remove nil?))]

View File

@@ -1,10 +1,9 @@
(ns frontend.modules.instrumentation.sentry
(:require [frontend.version :refer [version]]
[frontend.util :as util]
(:require ["@sentry/react" :as Sentry]
[frontend.config :as config]
[medley.core :as medley]
["@sentry/react" :as Sentry]
[frontend.mobile.util :as mobile-util]))
[frontend.mobile.util :as mobile-util]
[frontend.util :as util]
[frontend.version :refer [version]]))
(goog-define SENTRY-DSN "")
@@ -35,25 +34,25 @@
(re-matches #"file://.*?/(app/index|static/index)\.html(.*)" (.. event -request -url))]
(set! (.. event -request -url) (str "http://localhost/index.html" query-and-fragment)))
(let [*filtered (volatile! [])
^js values (.. event -exception -values)]
(doseq [[idx value] (medley/indexed values)]
(let [mf (some-> value (.. -mechanism -data -function))]
(when (contains? #{"setInterval"} mf)
(vswap! *filtered conj idx))
;; (let [*filtered (volatile! [])
;; ^js values (.. event -exception -values)]
;; (doseq [value (medley/indexed values)]
;; ;; (let [mf (some-> value (.. -mechanism -data -function))]
;; ;; (when (contains? #{"setInterval"} mf)
;; ;; (vswap! *filtered conj idx)))
(doseq [frame (.. value -stacktrace -frames)]
(when (not-empty (.. frame -filename))
(when-let [[_ filename]
(re-matches #"file://.*?/app/(js/.*\.js)" (.. frame -filename))]
(set! (.. frame -filename) (str "/static/" filename))
;; NOTE: No idea of why there's a 2-line offset.
(set! (.. frame -lineno) (- (.. frame -lineno) 2)))))))
;; (doseq [frame (.. value -stacktrace -frames)]
;; (when (not-empty (.. frame -filename))
;; (when-let [[_ filename]
;; (re-matches #"file://.*?/app/(js/.*\.js)" (.. frame -filename))]
;; (set! (.. frame -filename) (str "/static/" filename))
;; ;; NOTE: No idea of why there's a 2-line offset.
;; (set! (.. frame -lineno) (- (.. frame -lineno) 2))))))
;; remove filtered events
(when-let [filtered (seq @*filtered)]
(doseq [k filtered]
(js-delete values k))))
;; ;; remove filtered events
;; (when-let [filtered (seq @*filtered)]
;; (doseq [k filtered]
;; (js-delete values k))))
(catch :default e
(js/console.error e)))
event)})

View File

@@ -1,3 +1,3 @@
(ns ^:no-doc frontend.version)
(defonce version "0.10.10")
(defonce version "0.11.0")

View File

@@ -31,7 +31,6 @@
[frontend.worker.util :as worker-util]
[goog.object :as gobj]
[lambdaisland.glogi.console :as glogi-console]
[logseq.common.config :as common-config]
[logseq.common.util :as common-util]
[logseq.db :as ldb]
[logseq.db.common.order :as db-order]
@@ -174,7 +173,8 @@
(worker-util/post-message :capture-error
{:error "db-missing-addresses"
:payload {:missing-addresses missing-addresses}})
(prn :error :missing-addresses missing-addresses))))
(prn :error :missing-addresses missing-addresses))
missing-addresses))
(defn upsert-addr-content!
"Upsert addr+data-seq. Update sqlite-cli/upsert-addr-content! when making changes"
@@ -356,17 +356,12 @@
(when import-type {:import-type import-type}))]
(d/transact! conn initial-data {:initial-db? true})))
(when-not db-based?
(try
(when-not (ldb/page-exists? @conn common-config/views-page-name #{:logseq.class/Page})
(ldb/transact! conn (sqlite-create-graph/build-initial-views)))
(catch :default _e)))
(when-let [missing-addresses (seq (find-missing-addresses db))]
(throw (ex-info "DB missing addresses" {:missing-addresses missing-addresses})))
(find-missing-addresses db)
;; (gc-kvs-table! db)
(try
(db-migrate/migrate conn search-db)
(catch :default _e
(when db-based?
(rebuild-db-from-datoms! conn db import-type)
@@ -885,11 +880,13 @@
(= :thread-api/create-or-open-db method-k)
;; because shared-service operates at the graph level,
;; creating a new database or switching to another one requires re-initializing the service.
(p/let [method-args (ldb/read-transit-str (last args))
service (<init-service! (first method-args))]
;; wait for service ready
(let [[graph opts] (ldb/read-transit-str (last args))]
(if (:import-type opts)
(start-db! graph opts)
(p/let [service (<init-service! graph)]
(get-in service [:status :ready])
(js-invoke (:proxy service) k args))
;; wait for service ready
(js-invoke (:proxy service) k args))))
(or (contains? #{:thread-api/sync-app-state} method-k)
(nil? service))

View File

@@ -467,13 +467,13 @@
(def ^:private create-get-state-flow*
(let [rtc-loop-metadata-flow (m/watch *rtc-loop-metadata)]
(m/ap
(let [{rtc-lock :*rtc-lock
(let [{*rtc-lock' :*rtc-lock
:keys [repo graph-uuid local-graph-schema-version remote-graph-schema-version
user-uuid rtc-state-flow *rtc-auto-push? *rtc-remote-profile?
*online-users *last-stop-exception]}
(m/?< rtc-loop-metadata-flow)]
(try
(when (and repo rtc-state-flow *rtc-auto-push? rtc-lock)
(when (and repo rtc-state-flow *rtc-auto-push? *rtc-lock')
(m/?<
(m/latest
(fn [rtc-state rtc-auto-push? rtc-remote-profile?
@@ -493,7 +493,7 @@
:last-stop-exception-ex-data (some-> *last-stop-exception deref ex-data)})
rtc-state-flow
(m/watch *rtc-auto-push?) (m/watch *rtc-remote-profile?)
(m/watch rtc-lock) (m/watch *online-users)
(m/watch *rtc-lock') (m/watch *online-users)
(client-op/create-pending-block-ops-count-flow repo)
(rtc-log-and-state/create-local-t-flow graph-uuid)
(rtc-log-and-state/create-remote-t-flow graph-uuid))))