Merge branch 'master' into feat/custom-children-list-style

This commit is contained in:
charlie
2023-04-25 10:22:55 +08:00
57 changed files with 889 additions and 761 deletions

View File

@@ -2932,7 +2932,8 @@
custom-query? (boolean (:custom-query? config))]
(if (and (or ref? custom-query?) (not (:ref-query-child? config)))
(ui/lazy-visible
(fn [] (block-container-inner state repo config block)))
(fn [] (block-container-inner state repo config block))
{:debug-id (str "block-container-ref " (:db/id block))})
(block-container-inner state repo config block))))
(defn divide-lists
@@ -3360,7 +3361,7 @@
"More"
@*loading?
(ui/lazy-loading-placeholder)
(ui/lazy-loading-placeholder 88)
:else
"")})]))))
@@ -3452,8 +3453,7 @@
(rum/with-key
(breadcrumb-with-container blocks (assoc config :top-level? top-level?))
(:db/id parent)))))
{:debug-id page
:trigger-once? false})])))))]
{:debug-id page})])))))]
(and (:ref? config) (:group-by-page? config))
[:div.flex.flex-col

View File

@@ -209,7 +209,7 @@
[:span.px-3.flex (ui/icon "key")]
[:p.dark:text-gray-100
[:span "Please make sure you "]
"remember the password you have set, "
"remember the password you have set, as we are unable to reset or retrieve it in case you forget it, "
[:span "and we recommend you "]
"keep a secure backup "
[:span "of the password."]]]

View File

@@ -59,8 +59,7 @@
(blocks-cp repo page)
(ui/lazy-visible
(fn [] (blocks-cp repo page))
{:trigger-once? false
:debug-id (str "journal-blocks " page)}))
{:debug-id (str "journal-blocks " page)}))
{})

View File

@@ -253,5 +253,4 @@
(ui/lazy-visible
(fn []
(custom-query* config q (::query-triggered? state)))
{:debug-id q
:trigger-once? false})))
{:debug-id q})))

View File

@@ -12,6 +12,7 @@
[frontend.format.block :as block]
[medley.core :as medley]
[rum.core :as rum]
[logseq.graph-parser.text :as text]
[frontend.modules.outliner.tree :as tree]))
;; Util fns
@@ -27,7 +28,7 @@
(map #(medley/dissoc-in % ks) result)
result)))
(defn- sort-by-fn [sort-by-column item]
(defn- sort-by-fn [sort-by-column item {:keys [page?]}]
(case sort-by-column
:created-at
(:block/created-at item)
@@ -36,7 +37,7 @@
:block
(:block/content item)
:page
(:block/name item)
(if page? (:block/name item) (get-in item [:block/page :block/name]))
(get-in item [:block/properties sort-by-column])))
(defn- locale-compare
@@ -46,11 +47,12 @@
(< x y)
(.localeCompare (str x) (str y) (state/sub :preferred-language) #js {:numeric true})))
(defn- sort-result [result {:keys [sort-by-column sort-desc? sort-nlp-date?]}]
(defn- sort-result [result {:keys [sort-by-column sort-desc? sort-nlp-date? page?]}]
(if (some? sort-by-column)
(let [comp-fn (if sort-desc? #(locale-compare %2 %1) locale-compare)]
(sort-by (fn [item]
(block/normalize-block (sort-by-fn sort-by-column item) sort-nlp-date?))
(block/normalize-block (sort-by-fn sort-by-column item {:page? page?})
sort-nlp-date?))
comp-fn
result))
result))
@@ -115,7 +117,7 @@
(defn- build-column-value
"Builds a column's tuple value for a query table given a row, column and
options"
[row column {:keys [page? ->elem map-inline config]}]
[row column {:keys [page? ->elem map-inline config comma-separated-property?]}]
(case column
:page
[:string (if page?
@@ -143,9 +145,13 @@
[:string (when-let [updated-at (:block/updated-at row)]
(date/int->local-time-2 updated-at))]
[:string (or (get-in row [:block/properties-text-values column])
;; Fallback to property relationships for page blocks
(get-in row [:block/properties column]))]))
[:string (if comma-separated-property?
;; Return original properties since comma properties need to
;; return collections for display purposes
(get-in row [:block/properties column])
(or (get-in row [:block/properties-text-values column])
;; Fallback to original properties for page blocks
(get-in row [:block/properties column])))]))
(rum/defcs result-table < rum/reactive
(rum/local false ::select?)
@@ -165,7 +171,8 @@
;; Sort state needs to be in sync between final result and sortable title
;; as user needs to know if there result is sorted
sort-state (get-sort-state current-block)
result' (sort-result result sort-state)]
result' (sort-result result (assoc sort-state :page? page?))
property-separated-by-commas? (partial text/separated-by-commas? (state/get-config))]
[:div.overflow-x-auto {:on-mouse-down (fn [e] (.stopPropagation e))
:style {:width "100%"}
:class (when-not page? "query-table")}
@@ -188,7 +195,8 @@
{:page? page?
:->elem ->elem
:map-inline map-inline
:config config})]
:config config
:comma-separated-property? (property-separated-by-commas? column)})]
[:td.whitespace-nowrap {:on-mouse-down (fn []
(reset! *mouse-down? true)
(reset! select? false))

View File

@@ -16,7 +16,7 @@
(not (true? (state/scheduled-deadlines-disabled?)))
(= (string/lower-case page-name) (string/lower-case (date/journal-name)))))
(rum/defc scheduled-and-deadlines < rum/reactive db-mixins/query
(rum/defc scheduled-and-deadlines-inner < rum/reactive db-mixins/query
[page-name]
(let [scheduled-or-deadlines (when (scheduled-or-deadlines? page-name)
(db/get-date-scheduled-or-deadlines (string/capitalize page-name)))]
@@ -33,3 +33,9 @@
{})]
(content/content page-name {:hiccup ref-hiccup}))]
{:title-trigger? true})])))
(rum/defc scheduled-and-deadlines
[page-name]
(ui/lazy-visible
(fn [] (scheduled-and-deadlines-inner page-name))
{:debug-id "scheduled-and-deadlines"}))

View File

@@ -51,8 +51,12 @@
(defonce query-state (atom {}))
;; Current dynamic component
(def ^:dynamic *query-component*)
;; Which reactive queries are triggered by the current component
(def ^:dynamic *reactive-queries*)
;; component -> query-key
(defonce query-components (atom {}))
@@ -156,11 +160,14 @@
transform-fn identity}} query & inputs]
{:pre [(s/valid? ::react-query-keys k)]}
(let [kv? (and (vector? k) (= :kv (first k)))
origin-key k
k (vec (cons repo k))]
(when-let [db (conn/get-db repo)]
(let [result-atom (get-query-cached-result k)]
(when-let [component *query-component*]
(add-query-component! k component))
(when-let [queries *reactive-queries*]
(swap! queries conj origin-key))
(if (and use-cache? result-atom)
result-atom
(let [{:keys [result time]} (util/with-time

View File

@@ -3,10 +3,14 @@
(:require [frontend.db.react :as react]))
(def query
{:wrap-render
{:init
(fn [state]
(assoc state :reactive-queries (atom #{})))
:wrap-render
(fn [render-fn]
(fn [state]
(binding [react/*query-component* (:rum/react-component state)]
(binding [react/*query-component* (:rum/react-component state)
react/*reactive-queries* (:reactive-queries state)]
(render-fn state))))
:will-unmount
(fn [state]

View File

@@ -148,7 +148,7 @@
"")
(string/replace (re-pattern (str "(?i)" (gstring/regExpEscape (str "." ext)) "$"))
""))]
(util/safe-path-join repo-dir (str bak-dir "/" relative-path))))
(path/path-join repo-dir bak-dir relative-path)))
(defn- truncate-old-versioned-files!
"reserve the latest 6 version files"
@@ -174,7 +174,8 @@
dir (case dir
:backup-dir (get-backup-dir repo-dir path backup-dir ext)
:version-file-dir (get-backup-dir repo-dir path version-file-dir ext))
new-path (util/safe-path-join dir (str (string/replace (.toISOString (js/Date.)) ":" "_") "." (mobile-util/platform) "." ext))]
new-path (path/path-join dir (str (string/replace (.toISOString (js/Date.)) ":" "_") "." (mobile-util/platform) "." ext))]
(<write-file-with-utf8 new-path content)
(truncate-old-versioned-files! dir)))
@@ -187,14 +188,14 @@
(string/includes? repo-dir divider-schema))
repo-dir (if-not dir-schema?
(str file-schema divider-schema repo-dir) repo-dir)
backup-root (util/safe-path-join repo-dir backup-dir)
backup-root (path/path-join repo-dir backup-dir)
backup-dir-parent (util/node-path.dirname file-path)
backup-dir-parent (string/replace backup-dir-parent repo-dir "")
backup-dir-name (util/node-path.name file-path)
file-extname (.extname util/node-path file-path)
file-root (util/safe-path-join backup-root backup-dir-parent backup-dir-name)
file-path (util/safe-path-join file-root
(str (string/replace (.toISOString (js/Date.)) ":" "_") "." (mobile-util/platform) file-extname))]
file-root (path/path-join backup-root backup-dir-parent backup-dir-name)
file-path (path/path-join file-root
(str (string/replace (.toISOString (js/Date.)) ":" "_") "." (mobile-util/platform) file-extname))]
(<write-file-with-utf8 file-path content)
(truncate-old-versioned-files! file-root)))

View File

@@ -677,6 +677,7 @@
[:editor/bold
:editor/insert-link
:editor/italics
:editor/strike-through
:editor/highlight]
:shortcut.category/navigating

View File

@@ -1065,8 +1065,8 @@
(progress-bar width)])
(rum/defc lazy-loading-placeholder
[]
[:div.shadow.rounded-md.p-4.w-full.mx-auto.mb-5.fade-in {:style {:height 88}}
[height]
[:div.shadow.rounded-md.p-4.w-full.mx-auto.mb-5.fade-in {:style {:height height}}
[:div.animate-pulse.flex.space-x-4
[:div.flex-1.space-y-3.py-1
[:div.h-2.bg-base-4.rounded]
@@ -1076,37 +1076,37 @@
[:div.h-2.bg-base-4.rounded.col-span-1]]
[:div.h-2.bg-base-4.rounded]]]]])
(rum/defcs lazy-visible-inner
[state visible? content-fn ref]
[:div.lazy-visibility
{:ref ref
:style {:min-height 24}}
(if visible?
(when (fn? content-fn)
[:div.fade-enter
{:ref #(when-let [^js cls (and % (.-classList %))]
(.add cls "fade-enter-active"))}
(content-fn)])
(lazy-loading-placeholder))])
(rum/defc lazy-visible-inner
[visible? content-fn ref]
(let [[set-ref rect] (r/use-bounding-client-rect)
placeholder-height (or (when rect (.-height rect)) 88)]
[:div.lazy-visibility {:ref ref}
[:div {:ref set-ref}
(if visible?
(when (fn? content-fn)
[:div.fade-enter
{:ref #(when-let [^js cls (and % (.-classList %))]
(.add cls "fade-enter-active"))}
(content-fn)])
(lazy-loading-placeholder placeholder-height))]]))
(rum/defc lazy-visible
([content-fn]
(lazy-visible content-fn nil))
([content-fn {:keys [trigger-once? _debug-id]
:or {trigger-once? true}}]
(if (or (util/mobile?) (mobile-util/native-platform?))
(content-fn)
(let [[visible? set-visible!] (rum/use-state false)
inViewState (useInView #js {:rootMargin "100px"
:triggerOnce trigger-once?
:onChange (fn [in-view? entry]
(let [self-top (.-top (.-boundingClientRect entry))]
(when (or (and (not visible?) in-view?)
;; hide only the components below the current top for better ux
(and visible? (not in-view?) (> self-top 0)))
(set-visible! in-view?))))})
ref (.-ref inViewState)]
(lazy-visible-inner visible? content-fn ref)))))
:or {trigger-once? false}}]
(let [[visible? set-visible!] (rum/use-state false)
root-margin 100
inViewState (useInView #js {:rootMargin (str root-margin "px")
:triggerOnce trigger-once?
:onChange (fn [in-view? entry]
(let [self-top (.-top (.-boundingClientRect entry))]
(when (or (and (not visible?) in-view?)
;; hide only the components below the current top for better ux
(and visible? (not in-view?) (> self-top root-margin)))
(set-visible! in-view?))))})
ref (.-ref inViewState)]
(lazy-visible-inner visible? content-fn ref))))
(rum/defc portal
([children]

View File

@@ -528,13 +528,6 @@
(if (string? s)
(string/lower-case s) s))
#?(:cljs
(defn safe-path-join [prefix & paths]
(let [path (apply node-path.join (cons prefix paths))]
(if (and (electron?) (gstring/caseInsensitiveStartsWith path "file://"))
(gp-util/safe-decode-uri-component (subs path 7))
path))))
(defn trim-safe
[s]
(when s

View File

@@ -16,11 +16,11 @@
(when-let [result (query-dsl/query test-helper/test-db s)]
(map first (deref result))))
(deftest sort-result
(deftest sort-result-for-standard-columns
;; Define since it's not defined
(state/set-preferred-language! "en")
(testing "sort by block content"
(testing "sort by block column"
(are [sort-state result sorted-result]
(= (mapv #(hash-map :block/content %) sorted-result)
(#'query-table/sort-result (mapv #(hash-map :block/content %) result) sort-state))
@@ -30,6 +30,24 @@
{:sort-desc? false :sort-by-column :block}
["abc" "cde"] ["abc" "cde"]))
(testing "sort by page column"
(are [sort-options result sorted-result]
(= sorted-result
(#'query-table/sort-result result sort-options))
;; on page queries
{:sort-desc? true :sort-by-column :page :page? true}
(map #(hash-map :block/name %) ["abc" "cde"])
(map #(hash-map :block/name %) ["cde" "abc"])
;; on block queries
{:sort-desc? true :sort-by-column :page :page? false}
(map #(hash-map :block/page {:block/name %}) ["abc" "cde"])
(map #(hash-map :block/page {:block/name %}) ["cde" "abc"]))))
(deftest sort-result-for-property-columns
;; Define since it's not defined
(state/set-preferred-language! "en")
(testing "sort by integer block property"
(are [sort-state result sorted-result]
(= (mapv #(hash-map :block/properties %) sorted-result)
@@ -86,17 +104,17 @@
[{:title 1.1} {:title 1.2} {:title 1.11}]
[{:title 1.1} {:title 1.11} {:title 1.2}]))
(testing "sort by semver-style string block property"
(are [sort-state result sorted-result]
(= (mapv #(hash-map :block/properties %) sorted-result)
(#'query-table/sort-result (mapv #(hash-map :block/properties %) result) sort-state))
{:sort-desc? true :sort-by-column :title}
[{:title "1.1.0"} {:title "1.2.0"} {:title "1.11.0"} {:title "1.1.1"} {:title "1.11.1"} {:title "1.2.1"}]
[{:title "1.11.1"} {:title "1.11.0"} {:title "1.2.1"} {:title "1.2.0"} {:title "1.1.1"} {:title "1.1.0"}]
(testing "sort by semver-style string block property"
(are [sort-state result sorted-result]
(= (mapv #(hash-map :block/properties %) sorted-result)
(#'query-table/sort-result (mapv #(hash-map :block/properties %) result) sort-state))
{:sort-desc? true :sort-by-column :title}
[{:title "1.1.0"} {:title "1.2.0"} {:title "1.11.0"} {:title "1.1.1"} {:title "1.11.1"} {:title "1.2.1"}]
[{:title "1.11.1"} {:title "1.11.0"} {:title "1.2.1"} {:title "1.2.0"} {:title "1.1.1"} {:title "1.1.0"}]
{:sort-desc? false :sort-by-column :title}
[{:title "1.1.0"} {:title "1.2.0"} {:title "1.11.0"} {:title "1.1.1"} {:title "1.11.1"} {:title "1.2.1"}]
[{:title "1.1.0"} {:title "1.1.1"} {:title "1.2.0"} {:title "1.2.1"} {:title "1.11.0"} {:title "1.11.1"}]))
{:sort-desc? false :sort-by-column :title}
[{:title "1.1.0"} {:title "1.2.0"} {:title "1.11.0"} {:title "1.1.1"} {:title "1.11.1"} {:title "1.2.1"}]
[{:title "1.1.0"} {:title "1.1.1"} {:title "1.2.0"} {:title "1.2.1"} {:title "1.11.0"} {:title "1.11.1"}]))
(testing "sort by string block property for specific locale"
(state/set-preferred-language! "zh-CN")

View File

@@ -1,7 +1,9 @@
(ns frontend.db.query-dsl-test
(:require [cljs.test :refer [are deftest testing use-fixtures is]]
[clojure.string :as str]
[logseq.graph-parser.util.page-ref :as page-ref]
[frontend.db :as db]
[frontend.util :as util]
[frontend.db.query-dsl :as query-dsl]
[frontend.test.helper :as test-helper :include-macros true :refer [load-test-files]]))
@@ -142,6 +144,21 @@ prop-d:: nada"}])
(test-helper/with-config {}
(block-property-queries-test))))
(deftest block-property-query-performance
(let [pages (->> (repeat 10 {:tags ["tag1" "tag2"]})
(map-indexed (fn [idx {:keys [tags]}]
{:file/path (str "pages/page" idx ".md")
:file/content (if (seq tags)
(str "tags:: " (str/join ", " (map page-ref/->page-ref tags)))
"")})))
_ (load-test-files pages)
{:keys [result time]}
(util/with-time (dsl-query "(and (property tags tag1) (property tags tag2))"))]
;; Specific number isn't as important as ensuring query doesn't take orders
;; of magnitude longer
(is (> 25.0 time) "multi property query perf is reasonable")
(is (= 10 (count result)))))
(defn- page-property-queries-test
[]
(load-test-files [{:file/path "pages/page1.md"

View File

@@ -22,17 +22,6 @@
(is (= 2 (util/safe-inc-current-pos-from-start "abcde" 1)))
(is (= 1 (util/safe-inc-current-pos-from-start "中文" 0)))))
(deftest test-safe-path-join
(testing "safe path join with custom schema"
(is (= (util/node-path.join "a/b" "c/d.md") "a/b/c/d.md"))
(is (= (util/node-path.join "a/b/c" "../../d.md") "a/d.md"))
(is (= (util/node-path.join "file:///a/b" "c/d.md") "file:///a/b/c/d.md"))
(is (= (util/node-path.join "file:///a/b" "../d.md") "file:///a/d.md"))
(is (= (util/node-path.join "file:///a a2/b" "c/d.md") "file:///a a2/b/c/d.md"))
(is (= (util/node-path.join "C:/a2/b" "c/d.md") "C:/a2/b/c/d.md"))
(is (= (util/node-path.join "content://a/b" "../d.md") "content://a/d.md"))
(is (= (util/node-path.join "https://logseq.com/a/b" "c/d.md") "https://logseq.com/a/b/c/d.md"))))
(deftest test-memoize-last
(testing "memoize-last add test"
(let [actual-ops (atom 0)
@@ -120,4 +109,4 @@
(is (= (config/ext-of-video? "file.mp3") false))
(is (= (config/ext-of-image? "file.svg") true))
(is (= (config/ext-of-image? "a.file.png") true))
(is (= (config/ext-of-image? "file.tiff") false))))
(is (= (config/ext-of-image? "file.tiff") false))))