mirror of
https://github.com/logseq/logseq.git
synced 2026-04-24 14:14:55 +00:00
Merge branch 'feat/db' into feat/capacitor-new
This commit is contained in:
@@ -15,4 +15,5 @@
|
||||
:main-opts ["-m" "cognitect.test-runner"]
|
||||
:extra-deps {org.clojure/test.check {:mvn/version "1.1.1"}
|
||||
io.github.cognitect-labs/test-runner
|
||||
{:git/tag "v0.5.1" :git/sha "dfb30dd"}}}}}
|
||||
{:git/tag "v0.5.1" :git/sha "dfb30dd"}}}
|
||||
:dev {:extra-paths ["dev" "test"]}}}
|
||||
|
||||
73
clj-e2e/dev/user.clj
Normal file
73
clj-e2e/dev/user.clj
Normal file
@@ -0,0 +1,73 @@
|
||||
(ns user
|
||||
"fns used on repl"
|
||||
(:require [clojure.test :refer [run-tests run-test]]
|
||||
[logseq.e2e.config :as config]
|
||||
[logseq.e2e.editor-test]
|
||||
[logseq.e2e.fixtures :as fixtures]
|
||||
[logseq.e2e.multi-tabs-test]
|
||||
[logseq.e2e.outliner-test]
|
||||
[logseq.e2e.rtc-basic-test]
|
||||
[logseq.e2e.util :as util]
|
||||
[wally.main :as w]
|
||||
[wally.repl :as repl]))
|
||||
|
||||
;; Use port 3001 for local testing
|
||||
(reset! config/*port 3001)
|
||||
;; show ui
|
||||
(reset! config/*headless false)
|
||||
|
||||
(def *futures (atom {}))
|
||||
|
||||
(defn cancel
|
||||
[test-name]
|
||||
(some-> (get @*futures test-name) future-cancel)
|
||||
(swap! *futures dissoc test-name))
|
||||
|
||||
(defn run-editor-test
|
||||
[]
|
||||
(->> (future (run-tests 'logseq.e2e.editor-test))
|
||||
(swap! *futures assoc :editor-test)))
|
||||
|
||||
(defn run-outliner-test
|
||||
[]
|
||||
(->> (future (run-tests 'logseq.e2e.outliner-test))
|
||||
(swap! *futures assoc :outliner-test)))
|
||||
|
||||
(defn run-rtc-basic-test
|
||||
[]
|
||||
(->> (future (run-tests 'logseq.e2e.rtc-basic-test))
|
||||
(swap! *futures assoc :rtc-basic-test)))
|
||||
|
||||
(defn run-multi-tabs-test
|
||||
[]
|
||||
(->> (future (run-tests 'logseq.e2e.multi-tabs-test))
|
||||
(swap! *futures assoc :multi-tabs-test)))
|
||||
|
||||
(comment
|
||||
|
||||
(future
|
||||
(fixtures/open-page
|
||||
repl/pause
|
||||
{:headless false}))
|
||||
|
||||
;; You can put `(repl/pause)` in any test to pause the tests,
|
||||
;; this allows us to continue experimenting with the current page.
|
||||
(repl/pause)
|
||||
|
||||
;; To resume the tests, close the page/context/browser
|
||||
(repl/resume)
|
||||
|
||||
;; Run specific test
|
||||
(future (run-test logseq.e2e.editor-test/commands-test))
|
||||
|
||||
;; after the test has been paused, you can do anything with the current page like this
|
||||
(repl/with-page
|
||||
(w/wait-for (first (util/get-edit-block-container))
|
||||
{:state :detached}))
|
||||
|
||||
(run-tests 'logseq.e2e.editor-test
|
||||
'logseq.e2e.multi-tabs-test
|
||||
'logseq.e2e.outliner-test
|
||||
'logseq.e2e.rtc-basic-test)
|
||||
;;
|
||||
)
|
||||
22
clj-e2e/src/logseq/e2e/assert.clj
Normal file
22
clj-e2e/src/logseq/e2e/assert.clj
Normal file
@@ -0,0 +1,22 @@
|
||||
(ns logseq.e2e.assert
|
||||
(:import [com.microsoft.playwright.assertions PlaywrightAssertions])
|
||||
(:require [wally.main :as w]))
|
||||
|
||||
(def assert-that PlaywrightAssertions/assertThat)
|
||||
|
||||
(defn assert-is-visible
|
||||
[q]
|
||||
(-> (w/-query q) assert-that .isVisible))
|
||||
|
||||
(defn assert-is-hidden
|
||||
[q]
|
||||
(-> (w/-query q) assert-that .isHidden))
|
||||
|
||||
(defn assert-in-normal-mode?
|
||||
"- not editing mode
|
||||
- no action bar
|
||||
- no search(cmdk) modal"
|
||||
[]
|
||||
(assert-is-hidden (w/get-by-label "editing block"))
|
||||
(assert-is-hidden ".selection-action-bar")
|
||||
(assert-is-visible "#search-button"))
|
||||
5
clj-e2e/src/logseq/e2e/config.clj
Normal file
5
clj-e2e/src/logseq/e2e/config.clj
Normal file
@@ -0,0 +1,5 @@
|
||||
(ns logseq.e2e.config)
|
||||
|
||||
(defonce *port (atom 3002))
|
||||
(defonce *headless (atom true))
|
||||
(defonce *slow-mo (atom 100)) ; Set `slow-mo` lower to find more flaky tests
|
||||
24
clj-e2e/src/logseq/e2e/playwright_page.clj
Normal file
24
clj-e2e/src/logseq/e2e/playwright_page.clj
Normal file
@@ -0,0 +1,24 @@
|
||||
(ns logseq.e2e.playwright-page
|
||||
"operations on playwright pages."
|
||||
(:require [logseq.e2e.config :as config]
|
||||
[wally.main :as w]))
|
||||
|
||||
(defn get-pages
|
||||
[pw-ctx]
|
||||
(.pages pw-ctx))
|
||||
|
||||
(defn open-pages
|
||||
"Pages in same pw-ctx share cookies and storages"
|
||||
[pw-ctx n]
|
||||
(let [url (str "http://localhost:" @config/*port)]
|
||||
(dotimes [_i n]
|
||||
(let [page (.newPage pw-ctx)]
|
||||
(.navigate page url)
|
||||
;; wait the demo graph loaded
|
||||
(w/with-page page
|
||||
(w/wait-for "span.block-title-wrap"))))))
|
||||
|
||||
(defn close-pages
|
||||
[pages]
|
||||
(doseq [p pages]
|
||||
(.close p)))
|
||||
@@ -1,38 +0,0 @@
|
||||
(ns logseq.e2e.repl
|
||||
"fns used on repl"
|
||||
(:require [clojure.test :refer [run-tests run-test]]
|
||||
[logseq.e2e.util :as util]
|
||||
[wally.main :as w]
|
||||
[wally.repl :as repl]))
|
||||
|
||||
(comment
|
||||
|
||||
(future
|
||||
(w/with-page-open
|
||||
(w/make-page {:headless false
|
||||
:persistent false
|
||||
:slow-mo 20})
|
||||
(w/navigate "http://localhost:3001")
|
||||
(repl/pause)))
|
||||
|
||||
;; You can put `(repl/pause)` in any test to pause the tests,
|
||||
;; this allows us to continue experimenting with the current page.
|
||||
(repl/pause)
|
||||
|
||||
;; To resume the tests, close the page/context/browser
|
||||
(repl/resume)
|
||||
|
||||
;; Run all the tests in specific ns with `future` to not block repl
|
||||
(future (run-tests 'logseq.e2e.editor-test))
|
||||
(future (run-tests 'logseq.e2e.outliner-test))
|
||||
|
||||
;; Run specific test
|
||||
(future (run-test logseq.e2e.editor-test/commands-test))
|
||||
|
||||
;; after the test has been paused, you can do anything with the current page like this
|
||||
(repl/with-page
|
||||
(w/wait-for (first (util/get-edit-block-container))
|
||||
{:state :detached}))
|
||||
|
||||
;;
|
||||
)
|
||||
@@ -2,13 +2,11 @@
|
||||
(:refer-clojure :exclude [type])
|
||||
(:require [clojure.string :as string]
|
||||
[clojure.test :refer [is]]
|
||||
[logseq.e2e.assert :as assert]
|
||||
[logseq.e2e.keyboard :as k]
|
||||
[wally.main :as w]
|
||||
[wally.selectors :as ws]
|
||||
[logseq.e2e.keyboard :as k])
|
||||
(:import [com.microsoft.playwright TimeoutError]
|
||||
[com.microsoft.playwright.assertions PlaywrightAssertions]))
|
||||
|
||||
(def assert-that PlaywrightAssertions/assertThat)
|
||||
[wally.selectors :as ws])
|
||||
(:import [com.microsoft.playwright TimeoutError]))
|
||||
|
||||
(defn wait-timeout
|
||||
[ms]
|
||||
@@ -39,8 +37,16 @@
|
||||
(let [input-node (w/-query "*:focus")]
|
||||
(.type input-node text)))
|
||||
|
||||
(defn double-esc
|
||||
"Exits editing mode and ensure there's no action bar"
|
||||
[]
|
||||
(k/esc)
|
||||
(k/esc))
|
||||
|
||||
(defn search
|
||||
[text]
|
||||
(double-esc)
|
||||
(assert/assert-in-normal-mode?)
|
||||
(w/click :#search-button)
|
||||
(w/fill ".cp__cmdk-search-input" text))
|
||||
|
||||
@@ -48,6 +54,7 @@
|
||||
[title]
|
||||
;; Question: what's the best way to close all the popups?
|
||||
;; close popup, exit editing
|
||||
;; (repl/pause)
|
||||
(search title)
|
||||
(w/click [(ws/text "Create page") (ws/nth= "0")])
|
||||
(w/wait-for ".editor-wrapper textarea"))
|
||||
@@ -96,18 +103,6 @@
|
||||
(when-let [editor (get-editor)]
|
||||
(get-text editor)))
|
||||
|
||||
;; TODO: support tree
|
||||
(defn new-blocks
|
||||
[titles]
|
||||
(let [value (get-edit-content)]
|
||||
(if (string/blank? value) ; empty block
|
||||
(do
|
||||
(save-block (first titles))
|
||||
(doseq [title (rest titles)]
|
||||
(new-block title)))
|
||||
(doseq [title titles]
|
||||
(new-block title)))))
|
||||
|
||||
(defn bounding-xy
|
||||
[locator]
|
||||
(let [box (.boundingBox locator)]
|
||||
@@ -133,8 +128,23 @@
|
||||
|
||||
(defn open-last-block
|
||||
[]
|
||||
(double-esc)
|
||||
(assert/assert-in-normal-mode?)
|
||||
(w/click (last (w/query ".ls-page-blocks .ls-block .block-content"))))
|
||||
|
||||
;; TODO: support tree
|
||||
(defn new-blocks
|
||||
[titles]
|
||||
(open-last-block)
|
||||
(let [value (get-edit-content)]
|
||||
(if (string/blank? value) ; empty block
|
||||
(do
|
||||
(save-block (first titles))
|
||||
(doseq [title (rest titles)]
|
||||
(new-block title)))
|
||||
(doseq [title titles]
|
||||
(new-block title)))))
|
||||
|
||||
(defn repeat-keyboard
|
||||
[n shortcut]
|
||||
(dotimes [_i n]
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
(ns logseq.e2e.fixtures
|
||||
(:require [wally.main :as w]))
|
||||
(:require [wally.main :as w]
|
||||
[logseq.e2e.config :as config]
|
||||
[logseq.e2e.playwright-page :as pw-page]))
|
||||
|
||||
;; TODO: save trace
|
||||
;; TODO: parallel support
|
||||
(defn open-page
|
||||
[f & {:keys [headless port]
|
||||
:or {headless true
|
||||
port 3002}}]
|
||||
[f & {:keys [headless port]}]
|
||||
(w/with-page-open
|
||||
(w/make-page {:headless headless
|
||||
(w/make-page {:headless (or headless @config/*headless)
|
||||
:persistent false
|
||||
:slow-mo 100
|
||||
;; Set `slow-mo` lower to find more flaky tests
|
||||
;; :slow-mo 30
|
||||
:slow-mo @config/*slow-mo
|
||||
})
|
||||
(w/navigate (str "http://localhost:" port))
|
||||
(w/navigate (str "http://localhost:" (or port @config/*port)))
|
||||
(f)))
|
||||
|
||||
(def *page1 (atom nil))
|
||||
@@ -22,18 +20,17 @@
|
||||
|
||||
(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})]
|
||||
[f & {:keys [headless port]}]
|
||||
(let [headless (or headless @config/*headless)
|
||||
page-opts {:headless headless
|
||||
:persistent false
|
||||
:slow-mo @config/*slow-mo}
|
||||
p1 (w/make-page page-opts)
|
||||
p2 (w/make-page page-opts)
|
||||
port' (or port @config/*port)]
|
||||
(run!
|
||||
#(w/with-page %
|
||||
(w/navigate (str "http://localhost:" port)))
|
||||
(w/navigate (str "http://localhost:" port')))
|
||||
[p1 p2])
|
||||
|
||||
(reset! *page1 p1)
|
||||
@@ -42,3 +39,19 @@
|
||||
(f))
|
||||
(w/with-page-open p1)
|
||||
(w/with-page-open p2)))
|
||||
|
||||
(def ^:dynamic *pw-ctx* nil)
|
||||
(defn open-new-context
|
||||
"create a new playwright-context in `*pw-ctx*`"
|
||||
[f]
|
||||
(let [page-opts {:headless @config/*headless
|
||||
:persistent false
|
||||
:slow-mo @config/*slow-mo}
|
||||
p @(w/make-page page-opts)
|
||||
ctx (.newContext (.browser (.context p)))]
|
||||
;; context for p is no longer needed
|
||||
(.close (.context p))
|
||||
(w/with-page-open p) ; use with-page-open to close playwright instance
|
||||
(binding [*pw-ctx* ctx]
|
||||
(f)
|
||||
(.close (.browser *pw-ctx*)))))
|
||||
|
||||
23
clj-e2e/test/logseq/e2e/multi_tabs_test.clj
Normal file
23
clj-e2e/test/logseq/e2e/multi_tabs_test.clj
Normal file
@@ -0,0 +1,23 @@
|
||||
(ns logseq.e2e.multi-tabs-test
|
||||
(:require
|
||||
[clojure.test :refer [deftest testing is use-fixtures]]
|
||||
[logseq.e2e.fixtures :as fixtures]
|
||||
[logseq.e2e.playwright-page :as pw-page]
|
||||
[logseq.e2e.util :as util]
|
||||
[wally.main :as w]
|
||||
[wally.repl :as repl]))
|
||||
|
||||
(use-fixtures :once fixtures/open-new-context)
|
||||
|
||||
(deftest multi-tabs-test
|
||||
(testing "edit on one tab, check all tab's blocks are same"
|
||||
(pw-page/open-pages fixtures/*pw-ctx* 3)
|
||||
(let [[p1 p2 p3 :as pages] (pw-page/get-pages fixtures/*pw-ctx*)
|
||||
blocks-to-add (map #(str "b" %) (range 10))]
|
||||
(is (= 3 (count pages)))
|
||||
(w/with-page p1
|
||||
(util/new-blocks blocks-to-add))
|
||||
(w/with-page p2
|
||||
(is (= (util/page-blocks-count) (count blocks-to-add))))
|
||||
(w/with-page p3
|
||||
(is (= (util/page-blocks-count) (count blocks-to-add)))))))
|
||||
@@ -4,13 +4,10 @@
|
||||
[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]))
|
||||
[wally.main :as w]))
|
||||
|
||||
(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"
|
||||
@@ -23,7 +20,3 @@
|
||||
(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))
|
||||
|
||||
13
deps/shui/src/logseq/shui/dialog/core.cljs
vendored
13
deps/shui/src/logseq/shui/dialog/core.cljs
vendored
@@ -134,8 +134,7 @@
|
||||
(hooks/use-effect!
|
||||
(fn []
|
||||
(when (false? open?)
|
||||
(let [timeout (js/setTimeout #(detach-modal! id) 128)]
|
||||
#(js/clearTimeout timeout))))
|
||||
(detach-modal! id)))
|
||||
[open?])
|
||||
|
||||
(dialog
|
||||
@@ -159,12 +158,14 @@
|
||||
(cond-> (merge props content-props)
|
||||
auto-width? (assoc :data-auto-width true)
|
||||
(false? close-btn?) (assoc :data-close-btn false))
|
||||
(when title
|
||||
(dialog-header
|
||||
(when title (dialog-title title))
|
||||
(when description (dialog-description description))))
|
||||
|
||||
;; nested title component is required for radix dialog content
|
||||
(dialog-title {:class (when (nil? title) "hidden")} title)
|
||||
(when description (dialog-description description))
|
||||
|
||||
(when content
|
||||
[:div.ui__dialog-main-content content])
|
||||
|
||||
(when footer
|
||||
(dialog-footer footer)))))))
|
||||
|
||||
|
||||
1
deps/shui/src/logseq/shui/popup/core.cljs
vendored
1
deps/shui/src/logseq/shui/popup/core.cljs
vendored
@@ -178,7 +178,6 @@
|
||||
:top y
|
||||
:left x}} ""))
|
||||
(let [content-props (cond-> (merge content-props {:onEscapeKeyDown handle-key-escape!
|
||||
:disableOutsideScroll false
|
||||
:onPointerDownOutside handle-pointer-outside!})
|
||||
(and (not force-popover?)
|
||||
(not as-dropdown?))
|
||||
|
||||
3
deps/shui/src/logseq/shui/util.cljs
vendored
3
deps/shui/src/logseq/shui/util.cljs
vendored
@@ -27,7 +27,8 @@
|
||||
[data & {:keys [html-props]}]
|
||||
(let [convert-to-camel (fn [[key value]]
|
||||
(let [k (name key)]
|
||||
[(if-not (s/starts-with? k "data-")
|
||||
[(if-not (or (s/starts-with? k "data-")
|
||||
(s/starts-with? k "aria-"))
|
||||
(kebab-case->camel-case k) k) value]))]
|
||||
(w/postwalk (fn [x]
|
||||
(if (map? x)
|
||||
|
||||
@@ -80,6 +80,7 @@ const common = {
|
||||
'node_modules/react-dom/umd/react-dom.production.min.js',
|
||||
'node_modules/react-dom/umd/react-dom.development.js',
|
||||
'node_modules/prop-types/prop-types.min.js',
|
||||
'node_modules/dompurify/dist/purify.js',
|
||||
]).pipe(gulp.dest(path.join(outputPath, 'js'))),
|
||||
() => gulp.src([
|
||||
'node_modules/@tabler/icons-react/dist/umd/tabler-icons-react.min.js',
|
||||
|
||||
@@ -5,7 +5,7 @@ import '../src/index.css'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
// require in this file to keep app state when HMR
|
||||
const { setupGlobals } = require('../src')
|
||||
const { setupGlobals } = require('../src/ui')
|
||||
|
||||
setupGlobals()
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ const DialogContent = React.forwardRef<
|
||||
<DialogOverlay {...overlayProps}>
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
aria-describedby={undefined}
|
||||
className={cn(
|
||||
'ui__dialog-content',
|
||||
'relative grid w-full max-w-2xl lg:max-w-3xl gap-4 border sm:rounded-lg ' +
|
||||
|
||||
@@ -22,6 +22,7 @@ export function Toaster() {
|
||||
description,
|
||||
action,
|
||||
icon,
|
||||
onDismiss, // remove from toast props
|
||||
...props
|
||||
}) {
|
||||
const duration = props?.duration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'src/index.css'
|
||||
import { setupGlobals } from '../src'
|
||||
import '../src/index.css'
|
||||
import { setupGlobals } from '../src/ui'
|
||||
import * as React from 'react'
|
||||
import * as ReactDOM from 'react-dom'
|
||||
|
||||
|
||||
@@ -8,33 +8,30 @@
|
||||
"build:ui:only": "parcel build --target ui",
|
||||
"build:ui": "rm -rf .parcel-cache && yarn build:ui:only",
|
||||
"watch:storybook": "storybook dev -p 6006",
|
||||
"install:primitives": "rm -rf primitives/ && git clone -b x https://github.com/xyhp915/primitives.git --depth=1",
|
||||
"build:primitives": "yarn install:primitives && cd primitives/ && yarn install && yarn build",
|
||||
"preinstall": "test -f primitives/package.json || yarn build:primitives",
|
||||
"postinstall": "yarn build:ui"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^3.3.2",
|
||||
"@radix-ui/colors": "^3.0.0",
|
||||
"@radix-ui/react-alert-dialog": "^1.0.5",
|
||||
"@radix-ui/react-avatar": "^1.0.4",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-context-menu": "^2.1.5",
|
||||
"@radix-ui/react-dialog": "^1.1.2",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-popover": "^1.0.7",
|
||||
"@radix-ui/react-radio-group": "^1.1.3",
|
||||
"@radix-ui/react-select": "^2.0.0",
|
||||
"@radix-ui/react-separator": "^1.1.0",
|
||||
"@radix-ui/react-slider": "^1.1.2",
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
"@radix-ui/react-switch": "^1.0.3",
|
||||
"@radix-ui/react-tabs": "^1.1.1",
|
||||
"@radix-ui/react-toast": "^1.1.5",
|
||||
"@radix-ui/react-toggle": "^1.0.3",
|
||||
"@radix-ui/react-toggle-group": "^1.0.4",
|
||||
"@radix-ui/react-tooltip": "^1.1.4",
|
||||
"@radix-ui/react-alert-dialog": "^1.1.11",
|
||||
"@radix-ui/react-avatar": "^1.1.7",
|
||||
"@radix-ui/react-checkbox": "^1.2.3",
|
||||
"@radix-ui/react-context-menu": "^2.2.12",
|
||||
"@radix-ui/react-dialog": "^1.1.11",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.12",
|
||||
"@radix-ui/react-label": "^2.1.4",
|
||||
"@radix-ui/react-popover": "^1.1.11",
|
||||
"@radix-ui/react-radio-group": "^1.3.4",
|
||||
"@radix-ui/react-select": "^2.2.2",
|
||||
"@radix-ui/react-separator": "^1.1.4",
|
||||
"@radix-ui/react-slider": "^1.3.2",
|
||||
"@radix-ui/react-slot": "^1.2.0",
|
||||
"@radix-ui/react-switch": "^1.2.2",
|
||||
"@radix-ui/react-tabs": "^1.1.9",
|
||||
"@radix-ui/react-toast": "^1.2.11",
|
||||
"@radix-ui/react-toggle": "^1.1.6",
|
||||
"@radix-ui/react-toggle-group": "^1.1.7",
|
||||
"@radix-ui/react-tooltip": "^1.2.4",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.0.0",
|
||||
"cmdk": "^0.2.0",
|
||||
@@ -89,8 +86,7 @@
|
||||
},
|
||||
"react/jsx-dev-runtime": "./node_modules/react/jsx-dev-runtime.js",
|
||||
"react/jsx-runtime": "./node_modules/react/jsx-runtime.js",
|
||||
"@/*": "./@/$1",
|
||||
"@radix-ui/react-*": "./primitives/packages/react/$1"
|
||||
"@/*": "./@/$1"
|
||||
},
|
||||
"targets": {
|
||||
"main": false,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button } from '../@/components/ui/button'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Meta, StoryObj } from '@storybook/react'
|
||||
import { DropdownMenuCheckboxItemProps } from '@radix-ui/react-dropdown-menu'
|
||||
|
||||
@@ -73,6 +73,7 @@ export const Primary: StoryObj =
|
||||
<div className={'p-20'}>
|
||||
<DropdownMenuCheckboxes/>
|
||||
<Button onClick={() => {
|
||||
// @ts-ignore
|
||||
const p = toast({
|
||||
title: 'hello',
|
||||
description: <Button onClick={() => p.dismiss()}>hello</Button>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -69,6 +69,7 @@
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="./js/marked.min.js"></script>
|
||||
<script src="./js/purify.js"></script>
|
||||
<script>
|
||||
;(async function () {
|
||||
const app = document.getElementById('app')
|
||||
@@ -131,7 +132,7 @@
|
||||
}
|
||||
|
||||
content = marked.parse(content).replace('src="./', `src="${fixLink('')}`)
|
||||
setContent(content)
|
||||
setContent(DOMPurify.sanitize(content))
|
||||
}
|
||||
|
||||
// load default
|
||||
|
||||
@@ -495,12 +495,11 @@
|
||||
|
||||
(defmethod handle-action :trigger [_ state _event]
|
||||
(let [command (some-> state state->highlighted-item :source-command)
|
||||
dont-close-commands #{:graph/open :graph/remove :dev/replace-graph-with-db-file
|
||||
:ui/toggle-settings :go/flashcards :misc/import-edn-data}]
|
||||
dont-close-commands #{:graph/open :graph/remove :dev/replace-graph-with-db-file :misc/import-edn-data}]
|
||||
(when-let [action (:action command)]
|
||||
(action)
|
||||
(when-not (contains? dont-close-commands (:id command))
|
||||
(shui/dialog-close! :ls-dialog-cmdk)))))
|
||||
(shui/dialog-close! :ls-dialog-cmdk))
|
||||
(util/schedule #(action) 32))))
|
||||
|
||||
(defmethod handle-action :create [_ state _event]
|
||||
(let [item (state->highlighted-item state)
|
||||
|
||||
@@ -708,7 +708,6 @@
|
||||
(let [default-home (get-default-home-if-valid)
|
||||
current-repo (state/sub :git/current-repo)
|
||||
loading-files? (when current-repo (state/sub [:repo/loading-files? current-repo]))
|
||||
latest-journals (db/get-latest-journals (state/get-current-repo) 1)
|
||||
graph-parsing-state (state/sub [:graph/parsing-state current-repo])]
|
||||
(cond
|
||||
(or
|
||||
@@ -727,20 +726,17 @@
|
||||
(:page default-home))
|
||||
(route-handler/redirect-to-page! (:page default-home))
|
||||
|
||||
(and config/publishing?
|
||||
(not default-home)
|
||||
(empty? latest-journals))
|
||||
(let [latest-journals (db/get-latest-journals (state/get-current-repo) 1)]
|
||||
(and config/publishing?
|
||||
(not default-home)
|
||||
(empty? latest-journals)))
|
||||
(route-handler/redirect! {:to :all-pages})
|
||||
|
||||
loading-files?
|
||||
(ui/loading (t :loading-files))
|
||||
|
||||
(seq latest-journals)
|
||||
(journal/all-journals)
|
||||
|
||||
;; FIXME: why will this happen?
|
||||
:else
|
||||
[:div])])))
|
||||
(journal/all-journals))])))
|
||||
|
||||
(defn- hide-context-menu-and-clear-selection
|
||||
[e]
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
|
||||
(rum/defc remote-readme-display
|
||||
[{:keys [repo]} _content]
|
||||
(let [src (str (if (string/includes? js/location.href "logseq")
|
||||
(let [src (str (if (string/includes? js/location.host "logseq")
|
||||
"./static/" "./") "marketplace.html?repo=" repo)]
|
||||
[:iframe.lsp-frame-readme {:src src}]))
|
||||
|
||||
|
||||
@@ -235,8 +235,7 @@
|
||||
(state/pub-event! [:graph/open-new-window url])
|
||||
(cond
|
||||
;; exists locally?
|
||||
(or (:root graph)
|
||||
(and db-only? (not rtc-graph?)))
|
||||
(or (:root graph) (not rtc-graph?))
|
||||
(state/pub-event! [:graph/switch url])
|
||||
|
||||
(and rtc-graph? remote?)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
get-block-parent get-block-parents parents-collapsed? get-block-referenced-blocks
|
||||
get-block-immediate-children get-block-page
|
||||
get-custom-css
|
||||
get-file-last-modified-at get-file get-file-page get-file-page-id file-exists?
|
||||
get-file get-file-page get-file-page-id file-exists?
|
||||
get-files-blocks get-files-full get-journals-length
|
||||
get-latest-journals get-page get-case-page get-page-alias-names
|
||||
get-page-blocks-count get-page-blocks-no-cache get-page-file get-page-format
|
||||
|
||||
@@ -82,13 +82,6 @@
|
||||
(conn/get-db repo-url) pred)
|
||||
db-utils/seq-flatten)))
|
||||
|
||||
(defn get-file-last-modified-at
|
||||
[repo path]
|
||||
(when (and repo path)
|
||||
(when-let [db (conn/get-db repo)]
|
||||
(-> (db-utils/entity db [:file/path path])
|
||||
:file/last-modified-at))))
|
||||
|
||||
(defn file-exists?
|
||||
[repo path]
|
||||
(when (and repo path)
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
[clojure.string :as string]
|
||||
[frontend.config :as config]
|
||||
[frontend.db :as db]
|
||||
[frontend.db.async :as db-async]
|
||||
[frontend.db.model :as model]
|
||||
[frontend.fs :as fs]
|
||||
[logseq.common.path :as path]
|
||||
[frontend.handler.file-based.file :as file-handler]
|
||||
[frontend.handler.file-based.property :as file-property-handler]
|
||||
[frontend.handler.global-config :as global-config-handler]
|
||||
@@ -17,9 +17,9 @@
|
||||
[frontend.util.fs :as fs-util]
|
||||
[lambdaisland.glogi :as log]
|
||||
[logseq.common.config :as common-config]
|
||||
[logseq.common.path :as path]
|
||||
[logseq.common.util.block-ref :as block-ref]
|
||||
[promesa.core :as p]
|
||||
[frontend.db.async :as db-async]))
|
||||
[promesa.core :as p]))
|
||||
|
||||
;; all IPC paths must be normalized! (via common-util/path-normalize)
|
||||
|
||||
@@ -42,12 +42,11 @@
|
||||
(defn- handle-add-and-change!
|
||||
[repo path content db-content ctime mtime backup?]
|
||||
(let [config (state/get-config repo)
|
||||
path-hidden-patterns (:hidden config)
|
||||
db-last-modified-at (db/get-file-last-modified-at repo path)]
|
||||
path-hidden-patterns (:hidden config)]
|
||||
(when-not (or (and (seq path-hidden-patterns)
|
||||
(common-config/hidden? path path-hidden-patterns))
|
||||
(common-config/hidden? path path-hidden-patterns))
|
||||
;; File not changed
|
||||
(= db-last-modified-at mtime))
|
||||
(= content db-content))
|
||||
(p/let [;; save the previous content in a versioned bak file to avoid data overwritten.
|
||||
_ (when backup?
|
||||
(-> (when-let [repo-dir (config/get-local-dir repo)]
|
||||
|
||||
@@ -376,7 +376,7 @@
|
||||
:path-params {:name link}}))
|
||||
|
||||
(defmethod handle :graph/save-db-to-disk [[_ _opts]]
|
||||
(persist-db/export-current-graph! {:succ-notification? true}))
|
||||
(persist-db/export-current-graph! {:succ-notification? true :force-save? true}))
|
||||
|
||||
(defmethod handle :ui/re-render-root [[_]]
|
||||
(ui-handler/re-render-root!))
|
||||
|
||||
@@ -8,20 +8,20 @@
|
||||
[frontend.fs :as fs]
|
||||
[frontend.fs.nfs :as nfs]
|
||||
[frontend.handler.common :as common-handler]
|
||||
[frontend.handler.file-based.repo :as file-repo-handler]
|
||||
[frontend.handler.global-config :as global-config-handler]
|
||||
[frontend.handler.repo :as repo-handler]
|
||||
[frontend.handler.file-based.repo :as file-repo-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.idb :as idb]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
[frontend.persist-db :as persist-db]
|
||||
[frontend.state :as state]
|
||||
[frontend.util :as util]
|
||||
[frontend.util.fs :as util-fs]
|
||||
[goog.object :as gobj]
|
||||
[lambdaisland.glogi :as log]
|
||||
[logseq.common.util :as common-util]
|
||||
[promesa.core :as p]
|
||||
[frontend.persist-db :as persist-db]))
|
||||
[promesa.core :as p]))
|
||||
|
||||
(defn remove-ignore-files
|
||||
[files dir-name nfs?]
|
||||
@@ -273,7 +273,7 @@
|
||||
(when repo
|
||||
(p/do!
|
||||
(repo-handler/remove-repo! {:url repo} :switch-graph? false)
|
||||
(ls-dir-files-with-path! graph-dir)
|
||||
(ls-dir-files-with-path! graph-dir {:re-index? true})
|
||||
(when (fn? ok-handler) (ok-handler))))))
|
||||
|
||||
;; TODO: move to frontend.handler.repo
|
||||
|
||||
@@ -466,7 +466,6 @@
|
||||
|
||||
:graph/db-save {:fn #(state/pub-event! [:graph/save-db-to-disk])
|
||||
:inactive (not (util/electron?))
|
||||
:db-graph? true
|
||||
:binding "mod+s"}
|
||||
|
||||
:graph/re-index {:fn (fn []
|
||||
|
||||
@@ -42,10 +42,10 @@
|
||||
(<export-db repo {})))
|
||||
|
||||
(defn export-current-graph!
|
||||
[& {:keys [succ-notification?]}]
|
||||
[& {:keys [succ-notification? force-save?]}]
|
||||
(when (util/electron?)
|
||||
(when-let [repo (state/get-current-repo)]
|
||||
(when (config/db-based-graph? repo)
|
||||
(when (or (config/db-based-graph? repo) force-save?)
|
||||
(println :debug :save-db-to-disk repo)
|
||||
(->
|
||||
(p/do!
|
||||
|
||||
@@ -1248,7 +1248,9 @@
|
||||
#?(:cljs
|
||||
(defn scroll-editor-cursor
|
||||
[^js/HTMLElement el & {:keys [to-vw-one-quarter?]}]
|
||||
(when (and el (or (mobile-util/native-platform?) (mobile?)))
|
||||
(when (and el (or web-platform?
|
||||
(mobile-util/native-platform?)
|
||||
(mobile?)))
|
||||
(let [box-rect (.getBoundingClientRect el)
|
||||
box-top (.-top box-rect)
|
||||
box-bottom (.-bottom box-rect)
|
||||
@@ -1260,7 +1262,7 @@
|
||||
scroll-top' (.-scrollTop main-node)
|
||||
|
||||
current-pos (get-selection-start el)
|
||||
grapheme-pos (get-graphemes-pos (.-value (.textContent el)) current-pos)
|
||||
grapheme-pos (get-graphemes-pos (.-value el) current-pos)
|
||||
mock-text (some-> (gdom/getElement "mock-text")
|
||||
gdom/getChildren
|
||||
array-seq
|
||||
|
||||
@@ -880,13 +880,11 @@
|
||||
(= :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.
|
||||
(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])
|
||||
(let [[graph _opts] (ldb/read-transit-str (last args))]
|
||||
(p/let [service (<init-service! graph)]
|
||||
(get-in service [:status :ready])
|
||||
;; wait for service ready
|
||||
(js-invoke (:proxy service) k args))))
|
||||
(js-invoke (:proxy service) k args)))
|
||||
|
||||
(or (contains? #{:thread-api/sync-app-state} method-k)
|
||||
(nil? service))
|
||||
|
||||
@@ -328,26 +328,27 @@
|
||||
|
||||
{:proxy (js/Proxy. target
|
||||
#js {:get (fn [target method]
|
||||
(assert (identical? "remoteInvoke" method) method)
|
||||
(fn [args]
|
||||
(cond
|
||||
@*master-client?
|
||||
(<apply-target-f! target method args)
|
||||
(if (= "remoteInvoke" method)
|
||||
(fn [args]
|
||||
(cond
|
||||
@*master-client?
|
||||
(<apply-target-f! target method args)
|
||||
|
||||
:else
|
||||
(let [request-id (next-request-id)
|
||||
client-channel (ensure-client-channel client-id service-name)]
|
||||
(p/create
|
||||
(fn [resolve-fn reject-fn]
|
||||
(vswap! *requests-in-flight assoc request-id {:method method
|
||||
:args args
|
||||
:resolve-fn resolve-fn
|
||||
:reject-fn reject-fn})
|
||||
(.postMessage client-channel (bean/->js
|
||||
{:id request-id
|
||||
:type "request"
|
||||
:method method
|
||||
:args args}))))))))})
|
||||
:else
|
||||
(let [request-id (next-request-id)
|
||||
client-channel (ensure-client-channel client-id service-name)]
|
||||
(p/create
|
||||
(fn [resolve-fn reject-fn]
|
||||
(vswap! *requests-in-flight assoc request-id {:method method
|
||||
:args args
|
||||
:resolve-fn resolve-fn
|
||||
:reject-fn reject-fn})
|
||||
(.postMessage client-channel (bean/->js
|
||||
{:id request-id
|
||||
:type "request"
|
||||
:method method
|
||||
:args args})))))))
|
||||
(log/error :invalid-invoke-method method)))})
|
||||
:status status}))
|
||||
|
||||
(defn broadcast-to-clients!
|
||||
|
||||
Reference in New Issue
Block a user