瀏覽代碼

Merge branch 'master' into mrtracy/ref_sync_fix

Gabriel Horner 3 年之前
父節點
當前提交
04357919ff
共有 30 個文件被更改,包括 205 次插入131 次删除
  1. 2 2
      android/app/build.gradle
  2. 0 16
      e2e-tests/editor.spec.ts
  3. 1 0
      e2e-tests/page-search.spec.ts
  4. 4 4
      ios/App/App.xcodeproj/project.pbxproj
  5. 1 1
      resources/package.json
  6. 29 0
      scripts/build-ios.sh
  7. 12 2
      src/electron/electron/url.cljs
  8. 59 45
      src/main/electron/listener.cljs
  9. 1 0
      src/main/frontend/dicts.cljc
  10. 10 8
      src/main/frontend/extensions/tldraw.cljs
  11. 1 1
      src/main/frontend/fs/sync.cljs
  12. 2 2
      src/main/frontend/handler/common/file.cljs
  13. 15 8
      src/main/frontend/handler/events.cljs
  14. 1 1
      src/main/frontend/handler/page.cljs
  15. 20 2
      src/main/frontend/handler/repo.cljs
  16. 14 12
      src/main/frontend/search/agency.cljs
  17. 7 7
      src/main/frontend/ui.cljs
  18. 2 1
      src/main/frontend/util/fs.cljs
  19. 1 1
      src/main/frontend/version.cljs
  20. 3 3
      tldraw/apps/tldraw-logseq/src/app.tsx
  21. 6 1
      tldraw/apps/tldraw-logseq/src/components/BlockLink/BlockLink.tsx
  22. 1 1
      tldraw/apps/tldraw-logseq/src/lib/logseq-context.ts
  23. 2 2
      tldraw/demo/src/App.jsx
  24. 1 1
      tldraw/packages/react/src/components/BacklinksCountContainer/BacklinksCountContainer.tsx
  25. 1 0
      tldraw/packages/react/src/components/BacklinksCountContainer/index.ts
  26. 5 5
      tldraw/packages/react/src/components/Canvas/Canvas.tsx
  27. 0 0
      tldraw/packages/react/src/components/QuickLinksContainer/QuickLinksContainer.tsx
  28. 0 0
      tldraw/packages/react/src/components/QuickLinksContainer/index.ts
  29. 0 1
      tldraw/packages/react/src/components/ReferencesCountContainer/index.ts
  30. 4 4
      tldraw/packages/react/src/types/component-props.ts

+ 2 - 2
android/app/build.gradle

@@ -6,8 +6,8 @@ android {
         applicationId "com.logseq.app"
         applicationId "com.logseq.app"
         minSdkVersion rootProject.ext.minSdkVersion
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
-        versionCode 45
-        versionName "0.8.11"
+        versionCode 46
+        versionName "0.8.12"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         aaptOptions {
         aaptOptions {
              // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
              // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

+ 0 - 16
e2e-tests/editor.spec.ts

@@ -40,28 +40,12 @@ test('hashtag search page auto-complete', async ({ page, block }) => {
 
 
   await block.mustFill("done")
   await block.mustFill("done")
 
 
-  await enterNextBlock(page)
-  await page.type('textarea >> nth=0', 'Some#', { delay: 100 })
-  await page.waitForSelector('text="Search for a page"', { state: 'visible' })
-  await page.keyboard.press('Escape', { delay: 50 })
-
-  await block.mustFill("done")
-
   await enterNextBlock(page)
   await enterNextBlock(page)
   await page.type('textarea >> nth=0', 'Some #', { delay: 100 })
   await page.type('textarea >> nth=0', 'Some #', { delay: 100 })
   await page.waitForSelector('text="Search for a page"', { state: 'visible' })
   await page.waitForSelector('text="Search for a page"', { state: 'visible' })
   await page.keyboard.press('Escape', { delay: 50 })
   await page.keyboard.press('Escape', { delay: 50 })
 
 
   await block.mustFill("done")
   await block.mustFill("done")
-
-  await enterNextBlock(page)
-  await page.type('textarea >> nth=0', 'SomeInner', { delay: 100 })
-  for (let i = 0; i < 5; i++) {
-    await page.press('textarea >> nth=0', 'ArrowLeft', { delay: 50 })
-  }
-  await page.type('textarea >> nth=0', '#', { delay: 50 })
-  await page.waitForSelector('text="Search for a page"', { state: 'visible' })
-  await page.keyboard.press('Escape', { delay: 50 })
 })
 })
 
 
 test('disappeared children #4814', async ({ page, block }) => {
 test('disappeared children #4814', async ({ page, block }) => {

+ 1 - 0
e2e-tests/page-search.spec.ts

@@ -41,6 +41,7 @@ import { IsMac, createRandomPage, newBlock, newInnerBlock, randomString, lastBlo
   const results = await page.$$('#ui__ac-inner>div')
   const results = await page.$$('#ui__ac-inner>div')
   expect(results.length).toEqual(3) // 2 blocks + 1 page
   expect(results.length).toEqual(3) // 2 blocks + 1 page
   await page.keyboard.press("Escape")
   await page.keyboard.press("Escape")
+  await page.keyboard.press("Escape")
 })
 })
 
 
 async function alias_test(page: Page, page_name: string, search_kws: string[]) {
 async function alias_test(page: Page, page_name: string, search_kws: string[]) {

+ 4 - 4
ios/App/App.xcodeproj/project.pbxproj

@@ -515,7 +515,7 @@
 				INFOPLIST_FILE = App/Info.plist;
 				INFOPLIST_FILE = App/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
-				MARKETING_VERSION = 0.8.11;
+				MARKETING_VERSION = 0.8.12;
 				OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
 				OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -542,7 +542,7 @@
 				INFOPLIST_FILE = App/Info.plist;
 				INFOPLIST_FILE = App/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
-				MARKETING_VERSION = 0.8.11;
+				MARKETING_VERSION = 0.8.12;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
@@ -567,7 +567,7 @@
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
-				MARKETING_VERSION = 0.8.11;
+				MARKETING_VERSION = 0.8.12;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
@@ -594,7 +594,7 @@
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
-				MARKETING_VERSION = 0.8.11;
+				MARKETING_VERSION = 0.8.12;
 				MTL_FAST_MATH = YES;
 				MTL_FAST_MATH = YES;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
 				PRODUCT_BUNDLE_IDENTIFIER = com.logseq.logseq.ShareViewController;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";

+ 1 - 1
resources/package.json

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

+ 29 - 0
scripts/build-ios.sh

@@ -0,0 +1,29 @@
+#!/bin/bash
+
+set -ex
+
+unset LOGSEQ_APP_SERVER_URL
+export ENABLE_FILE_SYNC_PRODUCTION=true
+
+# yarn clean
+PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 yarn install --force
+
+rm -rv public/static || true
+rm -rv ios/App/App/public || true
+
+yarn release-app
+
+rsync -avz --exclude node_modules --exclude '*.js.map' --exclude android ./static/ ./public/static/
+
+npx cap sync ios
+
+npx cap open ios
+
+echo "step 1(Xcode). Product > Archive (device should be Any iOS Device)"
+
+echo "step 2(Archive). Distribute App"
+
+echo "  - App Store Connect"
+echo "  - Upload"
+echo "  - (Default config, all checked)"
+echo "  - Upload"

+ 12 - 2
src/electron/electron/url.cljs

@@ -63,11 +63,21 @@
   [^js win ^js/URL parsed-url]
   [^js win ^js/URL parsed-url]
   (let [action (.-pathname parsed-url)]
   (let [action (.-pathname parsed-url)]
     (cond
     (cond
+      ;; url:     (string) Page url
+      ;; title:   (stirng) Page title
+      ;; content: (string) Highlighted text
+      ;; page:    (string) Page name to insert to, use "TODAY" to insert to today page
+      ;; append:  (bool)   Append to the end of the page, default to false(current editing position)
       (= action "/quickCapture")
       (= action "/quickCapture")
-      (let [[url title content] (get-URL-decoded-params parsed-url ["url" "title" "content"])]
+      (let [[url title content page append] (get-URL-decoded-params parsed-url ["url" "title" "content" "page" "append"])]
         (send-to-focused-renderer "quickCapture" {:url url
         (send-to-focused-renderer "quickCapture" {:url url
                                                   :title title
                                                   :title title
-                                                  :content content} win))
+                                                  :content content
+                                                  :page page
+                                                  :append (if (nil? append)
+                                                            append
+                                                            (= append "true"))}
+                                  win))
 
 
       :else
       :else
       (send-to-focused-renderer "notification" {:type "error"
       (send-to-focused-renderer "notification" {:type "error"

+ 59 - 45
src/main/electron/listener.cljs

@@ -1,28 +1,28 @@
 (ns electron.listener
 (ns electron.listener
   "System-component-like ns that defines listeners by event name to receive ipc
   "System-component-like ns that defines listeners by event name to receive ipc
   messages from electron's main process"
   messages from electron's main process"
-  (:require
-    [cljs-bean.core :as bean]
-    [clojure.string :as string]
-    [datascript.core :as d]
-    [dommy.core :as dom]
-    [electron.ipc :as ipc]
-    [frontend.config :as config]
-    [frontend.context.i18n :refer [t]]
-    [frontend.date :as date]
-    [frontend.db :as db]
-    [frontend.db.model :as db-model]
-    [frontend.fs.sync :as sync]
-    [frontend.fs.watcher-handler :as watcher-handler]
-    [frontend.handler.editor :as editor-handler]
-    [frontend.handler.file-sync :as file-sync-handler]
-    [frontend.handler.notification :as notification]
-    [frontend.handler.repo :as repo-handler]
-    [frontend.handler.route :as route-handler]
-    [frontend.handler.ui :as ui-handler]
-    [frontend.handler.user :as user]
-    [frontend.state :as state]
-    [frontend.ui :as ui]))
+  (:require [cljs-bean.core :as bean]
+            [clojure.string :as string]
+            [datascript.core :as d]
+            [dommy.core :as dom]
+            [electron.ipc :as ipc]
+            [frontend.config :as config]
+            [frontend.context.i18n :refer [t]]
+            [frontend.date :as date]
+            [frontend.db :as db]
+            [frontend.db.model :as db-model]
+            [frontend.fs.sync :as sync]
+            [frontend.fs.watcher-handler :as watcher-handler]
+            [frontend.handler.editor :as editor-handler]
+            [frontend.handler.file-sync :as file-sync-handler]
+            [frontend.handler.notification :as notification]
+            [frontend.handler.repo :as repo-handler]
+            [frontend.handler.route :as route-handler]
+            [frontend.handler.ui :as ui-handler]
+            [frontend.handler.user :as user]
+            [frontend.state :as state]
+            [frontend.ui :as ui]
+            [frontend.handler.page :as page-handler]))
 
 
 
 
 (defn persist-dbs!
 (defn persist-dbs!
@@ -30,8 +30,8 @@
   ;; only persist current db!
   ;; only persist current db!
   ;; TODO rename the function and event to persist-db
   ;; TODO rename the function and event to persist-db
   (repo-handler/persist-db! {:before     #(notification/show!
   (repo-handler/persist-db! {:before     #(notification/show!
-                                            (ui/loading (t :graph/persist))
-                                            :warning)
+                                           (ui/loading (t :graph/persist))
+                                           :warning)
                              :on-success #(ipc/ipc "persistent-dbs-saved")
                              :on-success #(ipc/ipc "persistent-dbs-saved")
                              :on-error   #(ipc/ipc "persistent-dbs-error")}))
                              :on-error   #(ipc/ipc "persistent-dbs-error")}))
 
 
@@ -40,9 +40,9 @@
   []
   []
   ;; TODO: move "file-watcher" to electron.ipc.channels
   ;; TODO: move "file-watcher" to electron.ipc.channels
   (js/window.apis.on
   (js/window.apis.on
-    "persistent-dbs"
-    (fn [_req]
-      (persist-dbs!))))
+   "persistent-dbs"
+   (fn [_req]
+     (persist-dbs!))))
 
 
 
 
 (defn ^:large-vars/cleanup-todo listen-to-electron!
 (defn ^:large-vars/cleanup-todo listen-to-electron!
@@ -128,14 +128,14 @@
                      (fn [data]
                      (fn [data]
                        (let [repo (bean/->clj data)
                        (let [repo (bean/->clj data)
                              before-f #(notification/show!
                              before-f #(notification/show!
-                                         (ui/loading (t :graph/persist))
-                                         :warning)
+                                        (ui/loading (t :graph/persist))
+                                        :warning)
                              after-f #(ipc/ipc "broadcastPersistGraphDone")
                              after-f #(ipc/ipc "broadcastPersistGraphDone")
                              error-f (fn []
                              error-f (fn []
                                        (after-f)
                                        (after-f)
                                        (notification/show!
                                        (notification/show!
-                                         (t :graph/persist-error)
-                                         :error))
+                                        (t :graph/persist-error)
+                                        :error))
                              handlers {:before     before-f
                              handlers {:before     before-f
                                        :on-success after-f
                                        :on-success after-f
                                        :on-error   error-f}]
                                        :on-error   error-f}]
@@ -156,20 +156,27 @@
 
 
   (js/window.apis.on "quickCapture"
   (js/window.apis.on "quickCapture"
                      (fn [args]
                      (fn [args]
-                       (let [{:keys [url title content]} (bean/->clj args)
+                       (let [{:keys [url title content page append]} (bean/->clj args)
                              insert-today? (get-in (state/get-config)
                              insert-today? (get-in (state/get-config)
                                                    [:quick-capture-options :insert-today]
                                                    [:quick-capture-options :insert-today]
                                                    false)
                                                    false)
-                             today-page (string/lower-case (date/today))
-                             page (if (true? insert-today?)
+                             today-page (when (state/enable-journals?)
+                                          (string/lower-case (date/today)))
+                             page (if (or (= page "TODAY")
+                                          (and (string/blank? page) insert-today?))
                                     today-page
                                     today-page
-                                    (or (state/get-current-page)
-                                        today-page
-                                        "Quick Capture"))
+                                    (or (not-empty page)
+                                        (state/get-current-page)
+                                        today-page))
+                             page (or page "quick capture") ;; default to quick capture page, if journals are not enabled
                              format (db/get-page-format page)
                              format (db/get-page-format page)
                              time (date/get-current-time)
                              time (date/get-current-time)
                              text (or (and content (not-empty (string/trim content))) "")
                              text (or (and content (not-empty (string/trim content))) "")
-                             link (if (string/includes? url "www.youtube.com/watch") (str title " {{video " url "}}") (if (not-empty title) (config/link-format format title url) url))
+                             link (if (string/includes? url "www.youtube.com/watch")
+                                    (str title " {{video " url "}}")
+                                    (if (not-empty title)
+                                      (config/link-format format title url)
+                                      url))
                              template (get-in (state/get-config)
                              template (get-in (state/get-config)
                                               [:quick-capture-templates :text]
                                               [:quick-capture-templates :text]
                                               "**{time}** [[quick capture]]: {text} {url}")
                                               "**{time}** [[quick capture]]: {text} {url}")
@@ -178,13 +185,20 @@
                                          (string/replace "{url}" link)
                                          (string/replace "{url}" link)
                                          (string/replace "{text}" text))
                                          (string/replace "{text}" text))
                              edit-content (state/get-edit-content)
                              edit-content (state/get-edit-content)
-                             edit-content-include-capture? (and edit-content (string/includes? edit-content "[[quick capture]]"))]
-                         (if (and (state/editing?) (not edit-content-include-capture?))
-                           (editor-handler/insert (str "\n" content))
-                           (editor-handler/api-insert-new-block! content {:page page
-                                                                          :edit-block? false
-                                                                          :replace-empty-target? true})))))
-
+                             edit-content-blank? (string/blank? edit-content)
+                             edit-content-include-capture? (and (not-empty edit-content)
+                                                                (string/includes? edit-content "[[quick capture]]"))]
+                         (if (and (state/editing?) (not append) (not edit-content-include-capture?))
+                           (if edit-content-blank?
+                             (editor-handler/insert content)
+                             (editor-handler/insert (str "\n" content)))
+
+                           (do
+                             (when (not= page (state/get-current-page))
+                               (page-handler/create! page {:redirect? true}))
+                             (editor-handler/api-insert-new-block! content {:page page
+                                                                            :edit-block? true
+                                                                            :replace-empty-target? true}))))))
 
 
   (js/window.apis.on "openNewWindowOfGraph"
   (js/window.apis.on "openNewWindowOfGraph"
                      ;; Handle open new window in renderer, until the destination graph doesn't rely on setting local storage
                      ;; Handle open new window in renderer, until the destination graph doesn't rely on setting local storage

+ 1 - 0
src/main/frontend/dicts.cljc

@@ -1645,6 +1645,7 @@
            :settings-page/custom-date-format "首选日期页面格式"
            :settings-page/custom-date-format "首选日期页面格式"
            :settings-page/preferred-file-format "首选文件格式"
            :settings-page/preferred-file-format "首选文件格式"
            :settings-page/preferred-workflow "首选工作流"
            :settings-page/preferred-workflow "首选工作流"
+           :settings-page/preferred-pasting-file "保存链接为文件"
            :settings-page/enable-timetracking "开启 timetracking"
            :settings-page/enable-timetracking "开启 timetracking"
            :settings-page/enable-tooltip "开启提示框"
            :settings-page/enable-tooltip "开启提示框"
            :settings-page/enable-journals "开启日记"
            :settings-page/enable-journals "开启日记"

+ 10 - 8
src/main/frontend/extensions/tldraw.cljs

@@ -39,7 +39,6 @@
 
 
 (rum/defc block-reference
 (rum/defc block-reference
   [props]
   [props]
-  (println "page-name-linkpage-name-linkpage-name-linkpage-name-link" props)
   (block/block-reference {} (gobj/get props "blockId") nil))
   (block/block-reference {} (gobj/get props "blockId") nil))
 
 
 (rum/defc page-name-link
 (rum/defc page-name-link
@@ -73,7 +72,7 @@
                        :Block block-cp
                        :Block block-cp
                        :Breadcrumb breadcrumb
                        :Breadcrumb breadcrumb
                        :PageName page-name-link
                        :PageName page-name-link
-                       :ReferencesCount references-count
+                       :BacklinksCount references-count
                        :BlockReference block-reference})
                        :BlockReference block-reference})
 
 
 (defn get-tldraw-handlers [current-whiteboard-name]
 (defn get-tldraw-handlers [current-whiteboard-name]
@@ -91,13 +90,16 @@
                                                 (:db/id (model/get-page uuid))
                                                 (:db/id (model/get-page uuid))
                                                 (keyword type)))
                                                 (keyword type)))
    :redirectToPage (fn [page-name-or-uuid]
    :redirectToPage (fn [page-name-or-uuid]
-                     (let [page-name (if (util/uuid-string? page-name-or-uuid)
-                                       (:block/name (model/get-block-parent (parse-uuid page-name-or-uuid)))
-                                       page-name-or-uuid)
+                     (let [page-name (or (when (util/uuid-string? page-name-or-uuid)
+                                           (:block/name (model/get-block-page (state/get-current-repo)
+                                                                              (parse-uuid page-name-or-uuid))))
+                                         page-name-or-uuid)
+                           page-exists? (model/page-exists? page-name)
                            whiteboard? (model/whiteboard-page? page-name)]
                            whiteboard? (model/whiteboard-page? page-name)]
-                       (if whiteboard? (route-handler/redirect-to-whiteboard!
-                                        page-name {:block-id page-name-or-uuid})
-                           (route-handler/redirect-to-page! page-name-or-uuid))))})
+                       (when page-exists?
+                         (if whiteboard? (route-handler/redirect-to-whiteboard!
+                                          page-name {:block-id page-name-or-uuid})
+                             (route-handler/redirect-to-page! page-name-or-uuid)))))})
 
 
 (rum/defc tldraw-app
 (rum/defc tldraw-app
   [page-name block-id]
   [page-name block-id]

+ 1 - 1
src/main/frontend/fs/sync.cljs

@@ -494,7 +494,7 @@
         reserved-paths (filter f paths)]
         reserved-paths (filter f paths)]
     (when (seq reserved-paths)
     (when (seq reserved-paths)
       (let [paths (if path-string? reserved-paths (map -relative-path reserved-paths))]
       (let [paths (if path-string? reserved-paths (map -relative-path reserved-paths))]
-        (state/pub-event! [:ui/notify-files-with-reserved-chars paths])
+        (state/pub-event! [:ui/notify-outdated-filename-format paths])
         (prn "Skipped uploading those file paths with reserved chars: " paths)))
         (prn "Skipped uploading those file paths with reserved chars: " paths)))
     (vec (remove f paths))))
     (vec (remove f paths))))
 
 

+ 2 - 2
src/main/frontend/handler/common/file.cljs

@@ -37,7 +37,7 @@
   given page name and file path. This function is required when a file is being
   given page name and file path. This function is required when a file is being
   parsed from disk; before saving the parsed, blocks from the previous version
   parsed from disk; before saving the parsed, blocks from the previous version
   of that file need to be retracted.
   of that file need to be retracted.
-  
+
   The 'Page' parsed from the new file version is passed separately from the
   The 'Page' parsed from the new file version is passed separately from the
   file-path, as the page name can be set via properties in the file, and thus
   file-path, as the page name can be set via properties in the file, and thus
   can change between versions. If it has changed, existing blocks for both the
   can change between versions. If it has changed, existing blocks for both the
@@ -56,7 +56,7 @@
         tx (retract-blocks-tx blocks retain-uuids)]
         tx (retract-blocks-tx blocks retain-uuids)]
     (when-let [current-file (page-exists-in-another-file repo-url file-page file-path)]
     (when-let [current-file (page-exists-in-another-file repo-url file-page file-path)]
       (when (not= file-path current-file)
       (when (not= file-path current-file)
-        (let [error (str "Page already exists with another file: " current-file ", current file: " file-path)]
+        (let [error (str "Page already exists with another file: " current-file ", current file: " file-path ". Please keep only one of them and re-index your graph.")]
           (state/pub-event! [:notification/show
           (state/pub-event! [:notification/show
                              {:content error
                              {:content error
                               :status :error
                               :status :error

+ 15 - 8
src/main/frontend/handler/events.cljs

@@ -359,7 +359,11 @@
       (when-not dir-exists?
       (when-not dir-exists?
         (state/pub-event! [:graph/dir-gone dir]))))
         (state/pub-event! [:graph/dir-gone dir]))))
   ;; FIXME: an ugly implementation for redirecting to page on new window is restored
   ;; FIXME: an ugly implementation for redirecting to page on new window is restored
-  (repo-handler/graph-ready! repo))
+  (repo-handler/graph-ready! repo)
+  (when (and (util/electron?)
+             (not (config/demo-graph?))
+             (= :legacy (state/get-filename-format)))
+    (state/pub-event! [:ui/notify-outdated-filename-format []])))
 
 
 (defmethod handle :notification/show [[_ {:keys [content status clear?]}]]
 (defmethod handle :notification/show [[_ {:keys [content status clear?]}]]
   (notification/show! content status clear?))
   (notification/show! content status clear?))
@@ -738,7 +742,8 @@
     (when (= dir (config/get-repo-dir repo))
     (when (= dir (config/get-repo-dir repo))
       (fs/watch-dir! dir))))
       (fs/watch-dir! dir))))
 
 
-(defmethod handle :ui/notify-files-with-reserved-chars [[_ paths]]
+(defmethod handle :ui/notify-outdated-filename-format [[_ paths]]
+  ;; paths - the affected paths that contains reserved characters
   (notification/show!
   (notification/show!
    [:div
    [:div
     [:div.mb-4
     [:div.mb-4
@@ -746,9 +751,10 @@
 
 
      [:div
      [:div
       [:p
       [:p
-       "We suggest you upgrade now to avoid some potential bugs."]
-      [:p
-       "For example, the files below have reserved characters can't be synced on some platforms."]]
+       "We suggest you upgrade now to avoid potential bugs."]
+      (when (seq paths)
+        [:p
+         "For example, the files below have reserved characters that can't be synced on some platforms."])]
      ]
      ]
     (ui/button
     (ui/button
       "Update filename format"
       "Update filename format"
@@ -757,9 +763,10 @@
                   (state/set-modal!
                   (state/set-modal!
                   (fn [_] (conversion-component/files-breaking-changed))
                   (fn [_] (conversion-component/files-breaking-changed))
                   {:id :filename-format-panel :center? true})))
                   {:id :filename-format-panel :center? true})))
-    [:ol.my-2
-     (for [path paths]
-       [:li path])]]
+    (when (seq paths)
+      [:ol.my-2
+       (for [path paths]
+         [:li path])])]
    :warning
    :warning
    false))
    false))
 
 

+ 1 - 1
src/main/frontend/handler/page.cljs

@@ -100,7 +100,7 @@
 (defn- create-title-property?
 (defn- create-title-property?
   [journal? page-name]
   [journal? page-name]
   (and (not journal?)
   (and (not journal?)
-       (not= (state/get-filename-format) :triple-lowbar)
+       (= (state/get-filename-format) :legacy) ;; reduce title computation
        (fs-util/create-title-property? page-name)))
        (fs-util/create-title-property? page-name)))
 
 
 (defn- build-page-tx [format properties page journal? whiteboard?]
 (defn- build-page-tx [format properties page journal? whiteboard?]

+ 20 - 2
src/main/frontend/handler/repo.cljs

@@ -181,7 +181,9 @@
         chan (async/to-chan! indexed-files)
         chan (async/to-chan! indexed-files)
         graph-added-chan (async/promise-chan)
         graph-added-chan (async/promise-chan)
         total (count supported-files)
         total (count supported-files)
-        large-graph? (> total 1000)]
+        large-graph? (> total 1000)
+        *page-names (atom #{})
+        *page-name->path (atom {})]
     (when (seq delete-data) (db/transact! repo-url delete-data))
     (when (seq delete-data) (db/transact! repo-url delete-data))
     (state/set-current-repo! repo-url)
     (state/set-current-repo! repo-url)
     (state/set-parsing-state! {:total (count supported-files)})
     (state/set-parsing-state! {:total (count supported-files)})
@@ -215,7 +217,23 @@
                           (assoc opts' :skip-db-transact? false)
                           (assoc opts' :skip-db-transact? false)
                           opts')
                           opts')
                   result (parse-and-load-file! repo-url file opts')
                   result (parse-and-load-file! repo-url file opts')
-                  tx' (if whiteboard? tx (concat tx result))
+                  page-name (some (fn [x] (and (map? x) (:block/name x))) result)
+                  page-exists? (and page-name (get @*page-names page-name))
+                  tx' (cond
+                        whiteboard? tx
+                        page-exists? (do
+                                       (state/pub-event! [:notification/show
+                                                          {:content [:div
+                                                                     (util/format "The file \"%s\" will be skipped because another file \"%s\" has the same page title."
+                                                                                  (:file/path file)
+                                                                                  (get @*page-name->path page-name))]
+                                                           :status :warning
+                                                           :clear? false}])
+                                       tx)
+                        :else (concat tx result))
+                  _ (when (and page-name (not page-exists?))
+                      (swap! *page-names conj page-name)
+                      (swap! *page-name->path assoc page-name (:file/path file)))
                   tx' (if (or whiteboard? (zero? (rem (inc idx) 100)))
                   tx' (if (or whiteboard? (zero? (rem (inc idx) 100)))
                         (do (db/transact! repo-url tx' {:from-disk? true})
                         (do (db/transact! repo-url tx' {:from-disk? true})
                             [])
                             [])

+ 14 - 12
src/main/frontend/search/agency.cljs

@@ -9,13 +9,17 @@
 
 
 (defn get-registered-engines
 (defn get-registered-engines
   [repo]
   [repo]
-  (-> (if (util/electron?)
-        (search-node/->Node repo)
-        (search-browser/->Browser repo))
-      (cons
-       [(when state/lsp-enabled?
-          (for [s (state/get-all-plugin-services-with-type :search)]
-            (search-plugin/->Plugin s repo)))])))
+  [(if (util/electron?)
+     (search-node/->Node repo)
+     (search-browser/->Browser repo))
+   (when state/lsp-enabled?
+     (for [s (state/get-all-plugin-services-with-type :search)]
+       (search-plugin/->Plugin s repo)))])
+
+(defn- get-flatten-registered-engines
+  [repo]
+  (->> (flatten (get-registered-engines repo))
+       (remove nil?)))
 
 
 (deftype Agency [repo]
 (deftype Agency [repo]
   protocol/Engine
   protocol/Engine
@@ -36,17 +40,15 @@
 
 
   (transact-blocks! [_this data]
   (transact-blocks! [_this data]
     (println "D:Search > Transact blocks!:" repo)
     (println "D:Search > Transact blocks!:" repo)
-    (doseq [e (flatten (get-registered-engines repo))]
+    (doseq [e (get-flatten-registered-engines repo)]
       (protocol/transact-blocks! e data)))
       (protocol/transact-blocks! e data)))
 
 
   (truncate-blocks! [_this]
   (truncate-blocks! [_this]
     (println "D:Search > Truncate blocks!" repo)
     (println "D:Search > Truncate blocks!" repo)
-    (doseq [e (flatten (get-registered-engines repo))]
+    (doseq [e (get-flatten-registered-engines repo)]
       (protocol/truncate-blocks! e)))
       (protocol/truncate-blocks! e)))
 
 
   (remove-db! [_this]
   (remove-db! [_this]
     (println "D:Search > Remove Db!" repo)
     (println "D:Search > Remove Db!" repo)
-    (doseq [e (flatten (get-registered-engines repo))]
+    (doseq [e (get-flatten-registered-engines repo)]
       (protocol/remove-db! e))))
       (protocol/remove-db! e))))
-
-

+ 7 - 7
src/main/frontend/ui.cljs

@@ -246,7 +246,7 @@
            [:div.flex-shrink-0
            [:div.flex-shrink-0
             svg]
             svg]
            [:div.ml-3.w-0.flex-1
            [:div.ml-3.w-0.flex-1
-            [:div.text-sm.leading-5.font-medium.whitespace-pre-line {:style {:margin 0}}
+            [:div.text-sm.leading-6.font-medium.whitespace-pre-line {:style {:margin 0}}
              content]]
              content]]
            [:div.ml-4.flex-shrink-0.flex
            [:div.ml-4.flex-shrink-0.flex
             [:button.inline-flex.text-gray-400.focus:outline-none.focus:text-gray-500.transition.ease-in-out.duration-150.notification-close-button
             [:button.inline-flex.text-gray-400.focus:outline-none.focus:text-gray-500.transition.ease-in-out.duration-150.notification-close-button
@@ -942,24 +942,24 @@
   (memoize (fn [klass] (r/adapt-class klass))))
   (memoize (fn [klass] (r/adapt-class klass))))
 
 
 (defn icon
 (defn icon
-  ([class] (icon class nil))
-  ([class {:keys [extension? font?] :as opts}]
-   (when-not (string/blank? class)
+  ([name] (icon name nil))
+  ([name {:keys [extension? font? class] :as opts}]
+   (when-not (string/blank? name)
      (let [^js jsTablerIcons (gobj/get js/window "tablerIcons")]
      (let [^js jsTablerIcons (gobj/get js/window "tablerIcons")]
        (if (or extension? font? (not jsTablerIcons))
        (if (or extension? font? (not jsTablerIcons))
          [:span.ui__icon (merge {:class
          [:span.ui__icon (merge {:class
                                  (util/format
                                  (util/format
-                                  (str "%s-" class
+                                  (str "%s-" name
                                        (when (:class opts)
                                        (when (:class opts)
                                          (str " " (string/trim (:class opts)))))
                                          (str " " (string/trim (:class opts)))))
                                   (if extension? "tie tie" "ti ti"))}
                                   (if extension? "tie tie" "ti ti"))}
                                 (dissoc opts :class :extension? :font?))]
                                 (dissoc opts :class :extension? :font?))]
 
 
          ;; tabler svg react
          ;; tabler svg react
-         (when-let [klass (gobj/get js/tablerIcons (str "Icon" (csk/->PascalCase class)))]
+         (when-let [klass (gobj/get js/tablerIcons (str "Icon" (csk/->PascalCase name)))]
            (let [f (get-adapt-icon-class klass)]
            (let [f (get-adapt-icon-class klass)]
              [:span.ui__icon.ti
              [:span.ui__icon.ti
-              {:class (str "ls-icon-" class)}
+              {:class (str "ls-icon-" name " " class)}
               (f (merge {:size 18} (r/map-keys->camel-case (dissoc opts :class))))])))))))
               (f (merge {:size 18} (r/map-keys->camel-case (dissoc opts :class))))])))))))
 
 
 (defn button
 (defn button

+ 2 - 1
src/main/frontend/util/fs.cljs

@@ -179,7 +179,8 @@
    (when (string? title)
    (when (string? title)
      (case file-name-format
      (case file-name-format
        :triple-lowbar (tri-lb-file-name-sanity title)
        :triple-lowbar (tri-lb-file-name-sanity title)
-       :legacy-dot    (legacy-dot-file-name-sanity title) ;; The earliest file name rule (before May 2022). For file name check in the conversion logic only. Don't allow users to use this.
+       ;; The earliest file name rule (before May 2022). For file name check in the conversion logic only. Don't allow users to use this or show up in config, as it's not handled.
+       :legacy-dot    (legacy-dot-file-name-sanity title)
        (legacy-url-file-name-sanity title)))))
        (legacy-url-file-name-sanity title)))))
 
 
 (defn create-title-property?
 (defn create-title-property?

+ 1 - 1
src/main/frontend/version.cljs

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

+ 3 - 3
tldraw/apps/tldraw-logseq/src/app.tsx

@@ -57,12 +57,12 @@ interface LogseqTldrawProps {
   onPersist?: TLReactCallbacks<Shape>['onPersist']
   onPersist?: TLReactCallbacks<Shape>['onPersist']
 }
 }
 
 
-const ReferencesCount: LogseqContextValue['renderers']['ReferencesCount'] = props => {
+const BacklinksCount: LogseqContextValue['renderers']['BacklinksCount'] = props => {
   const { renderers } = React.useContext(LogseqContext)
   const { renderers } = React.useContext(LogseqContext)
 
 
   const options = { 'portal?': false }
   const options = { 'portal?': false }
 
 
-  return <renderers.ReferencesCount {...props} options={options} />
+  return <renderers.BacklinksCount {...props} options={options} />
 }
 }
 
 
 const AppImpl = () => {
 const AppImpl = () => {
@@ -71,7 +71,7 @@ const AppImpl = () => {
   const components = React.useMemo(
   const components = React.useMemo(
     () => ({
     () => ({
       ContextBar,
       ContextBar,
-      ReferencesCount,
+      BacklinksCount,
       QuickLinks,
       QuickLinks,
     }),
     }),
     []
     []

+ 6 - 1
tldraw/apps/tldraw-logseq/src/components/BlockLink/BlockLink.tsx

@@ -13,7 +13,12 @@ export const BlockLink = ({ id }: { id: string }) => {
   let linkType = validUUID(id) ? 'B' : 'P'
   let linkType = validUUID(id) ? 'B' : 'P'
 
 
   if (validUUID(id)) {
   if (validUUID(id)) {
-    if (queryBlockByUUID(id)?.properties?.['ls-type'] === 'whiteboard-shape') {
+    const block = queryBlockByUUID(id)
+    if (!block) {
+      return <span className='p-2'>Invalid reference. Did you remove it?</span>
+    }
+
+    if (block.properties?.['ls-type'] === 'whiteboard-shape') {
       iconName = 'link-to-whiteboard'
       iconName = 'link-to-whiteboard'
     } else {
     } else {
       iconName = 'link-to-block'
       iconName = 'link-to-block'

+ 1 - 1
tldraw/apps/tldraw-logseq/src/lib/logseq-context.ts

@@ -25,7 +25,7 @@ export interface LogseqContextValue {
     BlockReference: React.FC<{
     BlockReference: React.FC<{
       blockId: string
       blockId: string
     }>
     }>
-    ReferencesCount: React.FC<{
+    BacklinksCount: React.FC<{
       id: string
       id: string
       className?: string
       className?: string
       options?: {
       options?: {

+ 2 - 2
tldraw/demo/src/App.jsx

@@ -87,7 +87,7 @@ const PageName = props => {
   )
   )
 }
 }
 
 
-const ReferencesCount = props => {
+const BacklinksCount = props => {
   return (
   return (
     <div className={props.className}>
     <div className={props.className}>
       <div className={'open-page-ref-link rounded bg-gray-400 p-0.5 '}>3</div>
       <div className={'open-page-ref-link rounded bg-gray-400 p-0.5 '}>3</div>
@@ -222,7 +222,7 @@ export default function App() {
           Block,
           Block,
           Breadcrumb,
           Breadcrumb,
           PageName,
           PageName,
-          ReferencesCount,
+          BacklinksCount,
           BlockReference,
           BlockReference,
         }}
         }}
         handlers={{
         handlers={{

+ 1 - 1
tldraw/packages/react/src/components/ReferencesCountContainer/ReferencesCountContainer.tsx → tldraw/packages/react/src/components/BacklinksCountContainer/BacklinksCountContainer.tsx

@@ -24,7 +24,7 @@ export const BacklinksCountContainer = observer(function BacklinksCountContainer
 
 
   const app = useApp<S>()
   const app = useApp<S>()
 
 
-  if (!BacklinksCount) throw Error('Expected a ReferencesCount component.')
+  if (!BacklinksCount) throw Error('Expected a BacklinksCount component.')
 
 
   const stop: React.EventHandler<any> = e => e.stopPropagation()
   const stop: React.EventHandler<any> = e => e.stopPropagation()
 
 

+ 1 - 0
tldraw/packages/react/src/components/BacklinksCountContainer/index.ts

@@ -0,0 +1 @@
+export * from './BacklinksCountContainer'

+ 5 - 5
tldraw/packages/react/src/components/Canvas/Canvas.tsx

@@ -22,8 +22,8 @@ import { Container } from '../Container'
 import { ContextBarContainer } from '../ContextBarContainer'
 import { ContextBarContainer } from '../ContextBarContainer'
 import { HTMLLayer } from '../HTMLLayer'
 import { HTMLLayer } from '../HTMLLayer'
 import { Indicator } from '../Indicator'
 import { Indicator } from '../Indicator'
-import { QuickLinksContainer } from '../ReferencesCountContainer copy'
-import { BacklinksCountContainer } from '../ReferencesCountContainer'
+import { QuickLinksContainer } from '../QuickLinksContainer'
+import { BacklinksCountContainer } from '../BacklinksCountContainer'
 import { SelectionDetailContainer } from '../SelectionDetailContainer'
 import { SelectionDetailContainer } from '../SelectionDetailContainer'
 import { Shape } from '../Shape'
 import { Shape } from '../Shape'
 import { SVGContainer } from '../SVGContainer'
 import { SVGContainer } from '../SVGContainer'
@@ -158,11 +158,11 @@ export const Canvas = observer(function Renderer<S extends TLReactShape>({
           {hoveredShape && (
           {hoveredShape && (
             <Indicator key={'hovered_indicator_' + hoveredShape.id} shape={hoveredShape} />
             <Indicator key={'hovered_indicator_' + hoveredShape.id} shape={hoveredShape} />
           )}
           )}
-          {selectedOrHooveredShape && components.BacklinksCount && (
+          {singleSelectedShape && components.BacklinksCount && (
             <BacklinksCountContainer
             <BacklinksCountContainer
               hidden={false}
               hidden={false}
-              bounds={selectedOrHooveredShape.bounds}
-              shape={selectedOrHooveredShape}
+              bounds={singleSelectedShape.bounds}
+              shape={singleSelectedShape}
             />
             />
           )}
           )}
           {hoveredShape && hoveredShape !== singleSelectedShape && components.QuickLinks && (
           {hoveredShape && hoveredShape !== singleSelectedShape && components.QuickLinks && (

+ 0 - 0
tldraw/packages/react/src/components/ReferencesCountContainer copy/QuickLinksContainer.tsx → tldraw/packages/react/src/components/QuickLinksContainer/QuickLinksContainer.tsx


+ 0 - 0
tldraw/packages/react/src/components/ReferencesCountContainer copy/index.ts → tldraw/packages/react/src/components/QuickLinksContainer/index.ts


+ 0 - 1
tldraw/packages/react/src/components/ReferencesCountContainer/index.ts

@@ -1 +0,0 @@
-export * from './ReferencesCountContainer'

+ 4 - 4
tldraw/packages/react/src/types/component-props.ts

@@ -72,14 +72,14 @@ export type TLHandleComponent<
   H extends TLHandle = TLHandle
   H extends TLHandle = TLHandle
 > = (props: TLHandleComponentProps<S, H>) => JSX.Element | null
 > = (props: TLHandleComponentProps<S, H>) => JSX.Element | null
 
 
-export interface TLReferencesCountComponentProps<S extends TLReactShape = TLReactShape> {
+export interface TLBacklinksCountComponentProps<S extends TLReactShape = TLReactShape> {
   shape: S
   shape: S
   id: string
   id: string
   className?: string
   className?: string
 }
 }
 
 
-export type TLReferencesCountComponent<S extends TLReactShape = TLReactShape> = (
-  props: TLReferencesCountComponentProps<S>
+export type TLBacklinksCountComponent<S extends TLReactShape = TLReactShape> = (
+  props: TLBacklinksCountComponentProps<S>
 ) => JSX.Element | null
 ) => JSX.Element | null
 
 
 export interface TLQuickLinksComponentProps<S extends TLReactShape = TLReactShape> {
 export interface TLQuickLinksComponentProps<S extends TLReactShape = TLReactShape> {
@@ -102,7 +102,7 @@ export type TLReactComponents<S extends TLReactShape = TLReactShape> = {
   SelectionBackground?: TLBoundsComponent<S> | null
   SelectionBackground?: TLBoundsComponent<S> | null
   SelectionForeground?: TLBoundsComponent<S> | null
   SelectionForeground?: TLBoundsComponent<S> | null
   SelectionDetail?: TLSelectionDetailComponent<S> | null
   SelectionDetail?: TLSelectionDetailComponent<S> | null
-  BacklinksCount?: TLReferencesCountComponent<S> | null
+  BacklinksCount?: TLBacklinksCountComponent<S> | null
   QuickLinks?: TLQuickLinksComponent<S> | null
   QuickLinks?: TLQuickLinksComponent<S> | null
   DirectionIndicator?: TLDirectionIndicatorComponent<S> | null
   DirectionIndicator?: TLDirectionIndicatorComponent<S> | null
   Handle?: TLHandleComponent<S> | null
   Handle?: TLHandleComponent<S> | null