Browse Source

Merge branch 'master' into whiteboards

Peng Xiao 3 years ago
parent
commit
a72b28145c
40 changed files with 409 additions and 188 deletions
  1. 2 2
      .github/workflows/build-android.yml
  2. 2 2
      android/app/build.gradle
  3. 8 0
      ios/App/App.xcodeproj/project.pbxproj
  4. 13 0
      ios/App/App/Utils.m
  5. 22 0
      ios/App/App/Utils.swift
  6. 2 0
      package.json
  7. 6 0
      resources/css/animation.css
  8. 3 5
      resources/package.json
  9. 26 16
      src/main/frontend/components/block.cljs
  10. 16 0
      src/main/frontend/components/block.css
  11. 23 13
      src/main/frontend/components/header.css
  12. 7 7
      src/main/frontend/components/journal.cljs
  13. 1 1
      src/main/frontend/components/page_menu.cljs
  14. 4 4
      src/main/frontend/components/plugins.cljs
  15. 1 1
      src/main/frontend/components/reference.cljs
  16. 3 1
      src/main/frontend/components/sidebar.cljs
  17. 3 0
      src/main/frontend/components/sidebar.css
  18. 0 0
      src/main/frontend/components/svg.cljs
  19. 7 4
      src/main/frontend/db/query_react.cljs
  20. 1 0
      src/main/frontend/extensions/code.cljs
  21. 1 0
      src/main/frontend/handler.cljs
  22. 12 0
      src/main/frontend/handler/common.cljs
  23. 20 17
      src/main/frontend/handler/editor.cljs
  24. 5 1
      src/main/frontend/handler/page.cljs
  25. 30 32
      src/main/frontend/handler/ui.cljs
  26. 3 1
      src/main/frontend/mobile/core.cljs
  27. 26 21
      src/main/frontend/mobile/footer.cljs
  28. 18 3
      src/main/frontend/mobile/index.css
  29. 12 1
      src/main/frontend/mobile/util.cljs
  30. 5 2
      src/main/frontend/modules/shortcut/before.cljs
  31. 8 3
      src/main/frontend/state.cljs
  32. 44 42
      src/main/frontend/ui.cljs
  33. 8 0
      src/main/frontend/util.cljc
  34. 1 1
      src/main/frontend/version.cljs
  35. 19 3
      src/main/logseq/api.cljs
  36. 3 1
      src/main/logseq/graph_parser/block.cljc
  37. 0 1
      src/test/frontend/handler/repo_test.cljs
  38. 3 3
      src/test/frontend/modules/outliner/core_test.cljs
  39. 14 0
      templates/dummy-notes-it.md
  40. 27 0
      templates/tutorial-it.md

+ 2 - 2
.github/workflows/build-android.yml

@@ -89,8 +89,8 @@ jobs:
           sed -i 's/defonce version ".*"/defonce version "${{ steps.ref.outputs.version }}"/g' src/main/frontend/version.cljs
           sed -i 's/versionName ".*"/versionName "${{ steps.ref.outputs.version }}"/g' android/app/build.gradle
 
-      - name: Compile CLJS
-        run: yarn install && yarn release
+      - name: Compile CLJS - android variant, use es6 instead of es-next
+        run: yarn install && yarn release-android-app
 
       - name: Upload Sentry Sourcemaps (beta only)
         if: ${{ inputs.build-target == 'beta' || github.event.inputs.build-target == 'beta' }}

+ 2 - 2
android/app/build.gradle

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

+ 8 - 0
ios/App/App.xcodeproj/project.pbxproj

@@ -16,6 +16,8 @@
 		50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
 		5FD5BB71278579F5008E6875 /* DownloadiCloudFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FD5BB70278579F5008E6875 /* DownloadiCloudFiles.swift */; };
 		5FD5BB73278579FF008E6875 /* DownloadiCloudFiles.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FD5BB72278579FF008E6875 /* DownloadiCloudFiles.m */; };
+		5FF8632A283B5ADB0047731B /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FF86329283B5ADB0047731B /* Utils.swift */; };
+		5FF8632C283B5BFD0047731B /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FF8632B283B5BFD0047731B /* Utils.m */; };
 		5FFF7D6D27E343FA00B00DA8 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FFF7D6C27E343FA00B00DA8 /* ShareViewController.swift */; };
 		5FFF7D7027E343FA00B00DA8 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5FFF7D6E27E343FA00B00DA8 /* MainInterface.storyboard */; };
 		5FFF7D7427E343FA00B00DA8 /* ShareViewController.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 5FFF7D6A27E343FA00B00DA8 /* ShareViewController.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@@ -70,6 +72,8 @@
 		50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
 		5FD5BB70278579F5008E6875 /* DownloadiCloudFiles.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadiCloudFiles.swift; sourceTree = "<group>"; };
 		5FD5BB72278579FF008E6875 /* DownloadiCloudFiles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DownloadiCloudFiles.m; sourceTree = "<group>"; };
+		5FF86329283B5ADB0047731B /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
+		5FF8632B283B5BFD0047731B /* Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Utils.m; sourceTree = "<group>"; };
 		5FFF7D6A27E343FA00B00DA8 /* ShareViewController.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareViewController.appex; sourceTree = BUILT_PRODUCTS_DIR; };
 		5FFF7D6C27E343FA00B00DA8 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
 		5FFF7D6F27E343FA00B00DA8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
@@ -138,6 +142,8 @@
 		504EC3061FED79650016851F /* App */ = {
 			isa = PBXGroup;
 			children = (
+				5FF86329283B5ADB0047731B /* Utils.swift */,
+				5FF8632B283B5BFD0047731B /* Utils.m */,
 				5FD5BB72278579FF008E6875 /* DownloadiCloudFiles.m */,
 				5FD5BB70278579F5008E6875 /* DownloadiCloudFiles.swift */,
 				D32752BF2754C5AB0039291C /* AppDebug.entitlements */,
@@ -355,8 +361,10 @@
 				504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
 				5FD5BB71278579F5008E6875 /* DownloadiCloudFiles.swift in Sources */,
 				FE443F1E27FF54AA007ECE65 /* Payload.swift in Sources */,
+				5FF8632C283B5BFD0047731B /* Utils.m in Sources */,
 				FE8C946B27FD762700C8017B /* FileSync.swift in Sources */,
 				FE647FF427BDFEDE00F3206B /* FsWatcher.swift in Sources */,
+				5FF8632A283B5ADB0047731B /* Utils.swift in Sources */,
 				5FD5BB73278579FF008E6875 /* DownloadiCloudFiles.m in Sources */,
 				D3D62A0A275C92880003FBDC /* FileContainer.swift in Sources */,
 				D3D62A0C275C928F0003FBDC /* FileContainer.m in Sources */,

+ 13 - 0
ios/App/App/Utils.m

@@ -0,0 +1,13 @@
+//
+//  Utils.m
+//  Logseq
+//
+//  Created by leizhe on 2022/5/23.
+//
+
+#import <Foundation/Foundation.h>
+#import <Capacitor/Capacitor.h>
+
+CAP_PLUGIN(Utils, "Utils",
+           CAP_PLUGIN_METHOD(isZoomed, CAPPluginReturnPromise);
+           )

+ 22 - 0
ios/App/App/Utils.swift

@@ -0,0 +1,22 @@
+//
+//  Utils.swift
+//  Logseq
+//
+//  Created by leizhe on 2022/5/23.
+//
+
+import Foundation
+import Capacitor
+
+@objc(Utils)
+public class Utils: CAPPlugin  {
+    
+    @objc func isZoomed(_ call: CAPPluginCall) {
+        
+        var isZoomed: Bool {
+            return UIScreen.main.scale < UIScreen.main.nativeScale
+        }
+
+        call.resolve(["isZoomed": isZoomed])
+    }
+ }

+ 2 - 0
package.json

@@ -34,6 +34,7 @@
         "app-watch": "run-p gulp:watch cljs:app-watch",
         "release": "run-s gulp:build cljs:release",
         "release-app": "run-s gulp:build cljs:release-app",
+        "release-android-app": "run-s gulp:build cljs:release-android-app",
         "dev-release-app": "run-s gulp:build cljs:dev-release-app",
         "dev-electron-app": "gulp electron",
         "release-electron": "run-s gulp:build && gulp electronMaker",
@@ -55,6 +56,7 @@
         "cljs:release": "clojure -M:cljs release app publishing electron",
         "cljs:release-electron": "clojure -M:cljs release app electron --debug && clojure -M:cljs release publishing",
         "cljs:release-app": "clojure -M:cljs release app",
+        "cljs:release-android-app": "clojure -M:cljs release app --config-merge '{:compiler-options {:output-feature-set :es6}}'",
         "cljs:test": "clojure -M:test compile test",
         "cljs:run-test": "node static/tests.js",
         "cljs:dev-release-app": "clojure -M:cljs release app --config-merge '{:closure-defines {frontend.config/DEV-RELEASE true}}'",

+ 6 - 0
resources/css/animation.css

@@ -44,6 +44,12 @@
   animation-duration: 1s;
 }
 
+.faster-fade-in {
+  -webkit-animation-duration: 0.3s;
+  -moz-animation-duration: 0.3s;
+  animation-duration: 0.3s;
+}
+
 /* page transition */
 .fade-enter {
   opacity: 0;

+ 3 - 5
resources/package.json

@@ -1,6 +1,6 @@
 {
   "name": "Logseq",
-  "version": "0.6.10",
+  "version": "0.7.0",
   "main": "electron.js",
   "author": "Logseq",
   "license": "AGPL-3.0",
@@ -36,7 +36,7 @@
     "https-proxy-agent": "5.0.0",
     "@sentry/electron": "2.5.1",
     "posthog-js": "1.10.2",
-    "@logseq/rsapi": "0.0.14",
+    "@logseq/rsapi": "0.0.16",
     "electron-deeplink": "1.0.10"
   },
   "devDependencies": {
@@ -52,8 +52,6 @@
     "electron-rebuild": "3.2.5"
   },
   "resolutions": {
-    "@electron-forge/cli/**/colors": "1.4.0",
-    "electron-rebuild/**/colors": "1.4.0",
-    "electron-builder/**/colors": "1.4.0"
+    "**/electron": "15.1.2"
   }
 }

+ 26 - 16
src/main/frontend/components/block.cljs

@@ -509,6 +509,7 @@
 
     (if (or (not manual?) open?)
       (ui/tippy {:ref             *tippy-ref
+                 :in-editor?      true
                  :html            html-template
                  :interactive     true
                  :delay           [1000, 100]
@@ -764,6 +765,7 @@
                                           (db/get-block-and-children repo block-id)
                                           (assoc config :id (str id) :preview? true))]])
                         :interactive true
+                        :in-editor?  true
                         :delay       [1000, 100]} inner)
              inner)])
         [:span.warning.mr-1 {:title "Block ref invalid"}
@@ -1059,7 +1061,8 @@
      (when-not (string/blank? query)
        (custom-query (assoc config :dsl-query? true)
                      {:title (ui/tippy {:html commands/query-doc
-                                        :interactive true}
+                                        :interactive true
+                                        :in-editor?  true}
                                        [:span.font-medium.px-2.py-1.query-title.text-sm.rounded-md.shadow-xs
                                         (str "Query: " query)])
                       :query query})))])
@@ -1329,7 +1332,7 @@
 
       (= name "video")
       (macro-video-cp config arguments)
-      
+
       (contains? #{"tweet" "twitter"} name)
       (when-let [url (first arguments)]
         (let [id-regex #"/status/(\d+)"]
@@ -1984,6 +1987,7 @@
                                          (for [clock (take 10 (reverse clocks))]
                                            [:li clock])]])))
                     :interactive true
+                    :in-editor?  true
                     :delay       [1000, 100]}
                    [:div.text-sm.time-spent.ml-1 {:style {:padding-top 3}}
                     [:a.fade-link
@@ -2482,7 +2486,7 @@
        (fn []
          (block-container-inner state repo config block))
        nil
-       {:reset-height? false})
+       {})
       (block-container-inner state repo config block))))
 
 (defn divide-lists
@@ -2689,7 +2693,7 @@
                      (state/remove-custom-query-component! query)
                      (db/remove-custom-query! (state/get-current-repo) query))
                    state)}
-  [state config {:keys [title query view collapsed? children? breadcrumb-show?] :as q}]
+  [state config {:keys [title query view collapsed? children? breadcrumb-show? table-view?] :as q}]
   (let [dsl-query? (:dsl-query? config)
         query-atom (:query-atom state)
         current-block-uuid (or (:block/uuid (:block config))
@@ -2698,7 +2702,8 @@
         ;; exclude the current one, otherwise it'll loop forever
         remove-blocks (if current-block-uuid [current-block-uuid] nil)
         query-result (and query-atom (rum/react query-atom))
-        table? (or (get-in current-block [:block/properties :query-table])
+        table? (or table-view?
+                   (get-in current-block [:block/properties :query-table])
                    (and (string? query) (string/ends-with? (string/trim query) "table")))
         transformed-query-result (when query-result
                                    (db/custom-query-result-transform query-result remove-blocks q))
@@ -2727,8 +2732,8 @@
       [:code (if dsl-query?
                (util/format "{{query %s}}" query)
                "{{query hidden}}")]
-      [:div.custom-query.mt-4 (get config :attr {})
-       (when-not (and built-in? (empty? result))
+      (when-not (and built-in? (empty? result))
+        [:div.custom-query.mt-4 (get config :attr {})
          (ui/foldable
           [:div.custom-query-title
            [:span.title-text (cond
@@ -2741,7 +2746,7 @@
             (str (count transformed-query-result) " results")]]
           (fn []
             [:div
-             (when current-block
+             (when (and current-block (not view-f) (nil? table-view?))
                [:div.flex.flex-row.align-items.mt-2 {:on-mouse-down (fn [e] (util/stop e))}
                 (when-not page-list?
                   [:div.flex.flex-row
@@ -2803,7 +2808,7 @@
                :else
                [:div.text-sm.mt-2.ml-2.font-medium.opacity-50 "Empty"])])
           {:default-collapsed? collapsed?
-           :title-trigger? true}))])))
+           :title-trigger? true})]))))
 
 (rum/defc custom-query
   [config q]
@@ -2812,8 +2817,7 @@
    (ui/lazy-visible
     (fn [] (custom-query* config q))
     nil
-    {:reset-height? true})))
-
+    {})))
 (defn admonition
   [config type result]
   (when-let [icon (case (string/lower-case (name type))
@@ -3148,17 +3152,23 @@
 
 (rum/defcs breadcrumb-with-container < rum/reactive
   {:init (fn [state]
-           (assoc state ::navigating-block (atom (:block/uuid (ffirst (:rum/args state))))))}
+           (let [first-block (ffirst (:rum/args state))]
+             (assoc state
+                    ::initial-block    first-block
+                    ::navigating-block (atom (:block/uuid first-block)))))}
   [state blocks config]
   (let [repo (state/get-current-repo)
         *navigating-block (::navigating-block state)
         navigating-block (rum/react *navigating-block)
-        block (first blocks)
-        navigated? (and (not= (:block/uuid block) navigating-block) navigating-block)
+        navigating-block-entity (db/entity [:block/uuid navigating-block])
+        navigated? (and
+                    navigating-block
+                    (not= (:db/id (:block/parent (::initial-block state)))
+                          (:db/id (:block/parent navigating-block-entity))))
         blocks (if navigated?
-                 (let [block (db/pull [:block/uuid navigating-block])]
+                 (let [block navigating-block-entity]
                    (db/get-paginated-blocks repo (:db/id block)
-                                           {:scoped-block-id (:db/id block)}))
+                                            {:scoped-block-id (:db/id block)}))
                  blocks)]
     [:div
      (when (:breadcrumb-show? config)

+ 16 - 0
src/main/frontend/components/block.css

@@ -589,3 +589,19 @@ html.is-native-ios {
         width: 300px;
     }
 }
+
+html:not(.is-mac) {
+    body[data-active-keystroke="Control"] {
+        .block-content {
+            cursor: pointer;
+        }
+    }
+}
+
+html.is-mac {
+    body[data-active-keystroke="Meta"] {
+        .block-content {
+            cursor: pointer;
+        }
+    }
+}

+ 23 - 13
src/main/frontend/components/header.css

@@ -1,7 +1,7 @@
 .cp__header {
   @apply shadow z-10;
   -webkit-app-region: drag;
-  
+
   padding-top: var(--ls-headbar-inner-top-padding);
   height: calc(var(--ls-headbar-height) + var(--ls-headbar-inner-top-padding));
   display: flex;
@@ -9,14 +9,12 @@
   justify-content: space-between;
   flex: 0 0 auto;
   position: sticky;
-  position: -webkit-sticky;
   top: 0;
   left: 0;
   right: 0;
   user-select: none;
   line-height: 1;
   white-space: nowrap;
-  background-color: var(--ls-primary-background-color);
 
   > .l {
     width: var(--ls-left-sidebar-width);
@@ -207,7 +205,6 @@ a.button {
 }
 
 html.is-ios.is-safari {
-    
   .cp__header {
     background-color: var(--ls-primary-background-color);
   }
@@ -241,7 +238,7 @@ html.is-native-ipad {
              margin-top: 24px;
          }
     }
-    
+
     .cp__header > .r {
         display: flex;
     }
@@ -250,11 +247,11 @@ html.is-native-ipad {
 html.is-native-ipad {
     --ls-headbar-inner-top-padding: 0px;
     --ls-headbar-height: 4rem;
-    
+
     .cp__header {
       background-color: transparent !important;
       display: flex;
-      
+
       > .l {
         /* background-color: var(--ls-primary-background-color); */
         padding-top: 20px;
@@ -269,7 +266,7 @@ html.is-native-ipad {
         align-items: center;
       }
     }
-    
+
     .left-sidebar-inner  {
         > .wrap {
             padding-top: 20px;
@@ -291,7 +288,7 @@ html.is-native-ipad {
                 width: 12px;
                 height: 40vh;
             }
-            
+
             .resizer:hover {
                 background-color: var(--ls-guideline-color, #ddd);
             }
@@ -311,11 +308,11 @@ html.is-native-iphone {
             padding-bottom: 12px;
         }
     }
-    
+
     .ui__notifications {
         top: calc(var(--ls-headbar-height) + var(--ls-headbar-inner-top-padding) - 0.3rem);
     }
-    
+
     @media (orientation: landscape) {
         --ls-headbar-inner-top-padding: 8px;
         --ls-headbar-height: 2.5rem;
@@ -327,7 +324,7 @@ html.is-native-iphone {
 }
 
 html.is-native-iphone-without-notch {
-    
+
     --ls-headbar-inner-top-padding: 15px;
     --ls-headbar-height: 2.5rem;
 
@@ -335,7 +332,20 @@ html.is-native-iphone-without-notch {
 
         --ls-headbar-inner-top-padding: 0px;
         --ls-headbar-height: 2.5rem;
-     
+
+        .cp__header {
+            @apply shadow z-10;
+        }
+    }
+}
+
+html.is-zoomed-native-ios {
+    --ls-headbar-inner-top-padding: 30px;
+
+     @media (orientation: landscape) {
+        --ls-headbar-inner-top-padding: 8px;
+        --ls-headbar-height: 2.5rem;
+
         .cp__header {
             @apply shadow z-10;
         }

+ 7 - 7
src/main/frontend/components/journal.cljs

@@ -22,7 +22,7 @@
   (when-let [page-e (db/pull [:block/name (util/page-name-sanity-lc page)])]
     (page/page-blocks-cp repo page-e {})))
 
-(rum/defc journal-cp-inner < rum/reactive
+(rum/defc journal-cp < rum/reactive
   [[title format]]
   (let [;; Don't edit the journal title
         page (string/lower-case title)
@@ -54,7 +54,12 @@
        [:h1.title
         (gp-util/capitalize-all title)]]
 
-      (blocks-cp repo page format)
+      (if today?
+        (blocks-cp repo page format)
+        (ui/lazy-visible (fn []
+                           (blocks-cp repo page format))
+                         nil
+                         {}))
 
       {})
 
@@ -64,11 +69,6 @@
        (reference/references title)
        (str title "-refs"))]))
 
-(rum/defc journal-cp
-  [journal]
-  (ui/lazy-visible (fn [] (journal-cp-inner journal)) nil
-                   {:reset-height? true}))
-
 (rum/defc journals < rum/reactive
   [latest-journals]
   [:div#journals

+ 1 - 1
src/main/frontend/components/page_menu.cljs

@@ -147,7 +147,7 @@
             (for [[_ {:keys [label] :as cmd} action pid] (state/get-plugins-commands-with-type :page-menu-item)]
               {:title label
                :options {:on-click #(commands/exec-plugin-simple-command!
-                                     pid (assoc cmd :page (state/get-current-page)) action)}}))
+                                     pid (assoc cmd :page page-name) action)}}))
 
           (when developer-mode?
             {:title   "(Dev) Show page data"

+ 4 - 4
src/main/frontend/components/plugins.cljs

@@ -81,10 +81,10 @@
               group-first?      (:group-first opt)
               plg               (get (:plugin/installed-plugins @state/state) (keyword (:pid opt)))]
           [:div
+           {:key (str idx (:name opt))}
            (when (and group-first? (not= idx 0)) [:hr.my-2])
            [:div.it.flex.px-3.py-1.5.rounded-sm.justify-between
-            {:key      (str idx (:url opt))
-             :title    (:description opt)
+            {:title    (:description opt)
              :class    (util/classnames
                         [{:is-selected current-selected?
                           :is-active   (= idx @*cursor)}])
@@ -248,7 +248,7 @@
          :on-click #(when-not has-other-pending?
                       (plugin-handler/check-or-update-marketplace-plugin
                         (assoc item :only-check (not new-version))
-                        (fn [e] (notification/show! e :error))))}
+                        (fn [^js e] (notification/show! (.toString e) :error))))}
 
         (if installing-or-updating?
           (t :plugin/updating)
@@ -780,7 +780,7 @@
              (if-let [n (state/get-next-selected-coming-update)]
                (plugin-handler/check-or-update-marketplace-plugin
                  (assoc n :only-check false)
-                 (fn [^js e] (notification/show! e :error)))
+                 (fn [^js e] (notification/show! (.toString e) :error)))
                (plugin-handler/close-updates-downloading)))
 
           :disabled

+ 1 - 1
src/main/frontend/components/reference.cljs

@@ -170,7 +170,7 @@
     (fn []
       (references* page-name))
     nil
-    {:reset-height? false})))
+    {})))
 
 (rum/defcs unlinked-references-aux
   < rum/reactive db-mixins/query

+ 3 - 1
src/main/frontend/components/sidebar.cljs

@@ -24,6 +24,7 @@
             [frontend.handler.page :as page-handler]
             [frontend.handler.route :as route-handler]
             [frontend.handler.user :as user-handler]
+            [frontend.handler.common :as common-handler]
             [frontend.mixins :as mixins]
             [frontend.mobile.footer :as footer]
             [frontend.mobile.util :as mobile-util]
@@ -284,7 +285,8 @@
                    {:drop (fn [_e files]
                             (when-let [id (state/get-edit-input-id)]
                               (let [format (:block/format (state/get-edit-block))]
-                                (editor-handler/upload-asset id files format editor-handler/*asset-uploading? true))))}))
+                                (editor-handler/upload-asset id files format editor-handler/*asset-uploading? true))))})
+                  (common-handler/listen-to-scroll! element))
                 state)}
   [{:keys [route-match margin-less-pages? route-name indexeddb-support? db-restoring? main-content]}]
   (let [left-sidebar-open? (state/sub :ui/left-sidebar-open?)

+ 3 - 0
src/main/frontend/components/sidebar.css

@@ -30,6 +30,9 @@
 }
 
 #main-container {
+    /* Hack: (overflow-y) to fix sticky header not working */
+    /* To reproduce: quick creating blocks */
+    overflow-y: hidden;
     position: relative;
     height: 100%;
     transition: padding-left .3s;

File diff suppressed because it is too large
+ 0 - 0
src/main/frontend/components/svg.cljs


+ 7 - 4
src/main/frontend/db/query_react.cljs

@@ -12,6 +12,7 @@
             [frontend.state :as state]
             [logseq.graph-parser.text :as text]
             [frontend.util :as util]
+            [frontend.date :as date]
             [lambdaisland.glogi :as log]))
 
 (defn resolve-input
@@ -28,17 +29,19 @@
     (= :tomorrow input)
     (date->int (t/plus (t/today) (t/days 1)))
     (= :current-page input)
-    ;; This sometimes runs when there isn't a current page e.g. :home route
-    (some-> (state/get-current-page) string/lower-case)
+    (some-> (or (state/get-current-page)
+                (:page (state/get-default-home))
+                (date/today)) string/lower-case)
+
     (and (keyword? input)
          (util/safe-re-find #"^\d+d(-before)?$" (name input)))
     (let [input (name input)
-          days (parse-long (subs input 0 (dec (count input))))]
+          days (parse-long (re-find #"^\d+" input))]
       (date->int (t/minus (t/today) (t/days days))))
     (and (keyword? input)
          (util/safe-re-find #"^\d+d(-after)?$" (name input)))
     (let [input (name input)
-          days (parse-long (subs input 0 (dec (count input))))]
+          days (parse-long (re-find #"^\d+" input))]
       (date->int (t/plus (t/today) (t/days days))))
 
     (and (string? input) (text/page-ref? input))

+ 1 - 0
src/main/frontend/extensions/code.cljs

@@ -168,6 +168,7 @@
               new-content (if (string/blank? value)
                             (str prefix surfix)
                             (str prefix value "\n" surfix))]
+          (state/set-edit-content! (state/get-edit-input-id) new-content)
           (editor-handler/save-block-if-changed! block new-content))
 
         (:file-path config)

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

@@ -48,6 +48,7 @@
             ;;  false)
             ))))
 
+
 (defn- watch-for-date!
   []
   (let [f (fn []

+ 12 - 0
src/main/frontend/handler/common.cljs

@@ -139,3 +139,15 @@
       (log/error :parse/config-failed e)
       (state/pub-event! [:backup/broken-config (state/get-current-repo) content])
       (rewrite/parse-string config/config-default-content))))
+
+(defn listen-to-scroll!
+  [element]
+  (let [*scroll-timer (atom nil)]
+    (.addEventListener element "scroll"
+                       (fn []
+                         (when @*scroll-timer
+                           (js/clearTimeout @*scroll-timer))
+                         (state/set-state! :ui/scrolling? true)
+                         (reset! *scroll-timer (js/setTimeout
+                                                (fn [] (state/set-state! :ui/scrolling? false)) 500)))
+                       false)))

+ 20 - 17
src/main/frontend/handler/editor.cljs

@@ -590,6 +590,7 @@
                  edit-block? true}}]
   (when (or page block-uuid)
     (let [before? (if page false before?)
+          sibling? (boolean sibling?)
           sibling? (if before? true (if page false sibling?))
           block (if page
                   (db/entity [:block/name (util/page-name-sanity-lc page)])
@@ -1290,21 +1291,23 @@
                  db-content (:block/content db-block)
                  db-content-without-heading (and db-content
                                                  (gp-util/safe-subs db-content (:block/level db-block)))
-                 value (or (:block/content current-block)
-                           (and elem (gobj/get elem "value")))]
-             (cond
-               force?
-               (save-block-aux! db-block value opts)
-
-               (and skip-properties?
-                    (db-model/top-block? block)
-                    (when elem (thingatpt/properties-at-point elem)))
-               nil
-
-               (and block value db-content-without-heading
-                    (not= (string/trim db-content-without-heading)
-                          (string/trim value)))
-               (save-block-aux! db-block value opts)))
+                 value (if (= (:block/uuid current-block) (:block/uuid block))
+                         (:block/content current-block)
+                         (and elem (gobj/get elem "value")))]
+             (when value
+               (cond
+                 force?
+                 (save-block-aux! db-block value opts)
+
+                 (and skip-properties?
+                      (db-model/top-block? block)
+                      (when elem (thingatpt/properties-at-point elem)))
+                 nil
+
+                 (and block value db-content-without-heading
+                      (not= (string/trim db-content-without-heading)
+                            (string/trim value)))
+                 (save-block-aux! db-block value opts))))
            (catch js/Error error
              (log/error :save-block-failed error))))))))
 
@@ -2571,7 +2574,7 @@
 
       ;; just delete
       :else
-      (do
+      (when-not (mobile-util/native-ios?)
         (util/stop e)
         (delete-and-update
          input (util/safe-dec-current-pos-from-end (.-value input) current-pos) current-pos)))))
@@ -2906,7 +2909,7 @@
       (and (gp-util/url? text)
            (not (string/blank? (util/get-selected-text))))
       (html-link-format! text)
-      
+
       (and (text/block-ref? text)
            (wrapped-by? input "((" "))"))
       (commands/simple-insert! (state/get-edit-input-id) (text/get-block-ref text) nil)

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

@@ -98,8 +98,12 @@
                                                 (or
                                                  (:block/original-name page)
                                                  (:block/name page)))
-          page (if (seq properties) (assoc page :block/properties properties) page)]
+          page (if (seq properties) (assoc page :block/properties properties) page)
+          page-empty? (db/page-empty? (state/get-current-repo) (:block/name page))]
       (cond
+        (not page-empty?)
+        [page]
+
         create-title?
         (let [properties-block (default-properties-block (build-title page) format page-entity properties)]
           [page

+ 30 - 32
src/main/frontend/handler/ui.cljs

@@ -13,7 +13,6 @@
             [goog.object :as gobj]
             [clojure.string :as string]
             [rum.core :as rum]
-            [frontend.mobile.util :as mobile]
             [electron.ipc :as ipc]))
 
 (defn- get-css-var-value
@@ -135,37 +134,36 @@
 
 (defn exec-js-if-exists-&-allowed!
   [t]
-  (when-not (mobile/native-platform?)
-    (when-let [href (or
-                     (state/get-custom-js-link)
-                     (config/get-custom-js-path))]
-      (let [k (str "ls-js-allowed-" href)
-            execed #(swap! *js-execed conj href)
-            execed? (contains? @*js-execed href)
-            ask-allow #(let [r (js/confirm (t :plugin/custom-js-alert))]
-                         (if r
-                           (storage/set k (js/Date.now))
-                           (storage/set k false))
-                         r)
-            allowed! (storage/get k)
-            should-ask? (or (nil? allowed!)
-                            (> (- (js/Date.now) allowed!) 604800000))]
-        (when (and (not execed?)
-                   (not= false allowed!))
-          (if (string/starts-with? href "http")
-            (when (or (not should-ask?)
-                      (ask-allow))
-              (load href #(do (js/console.log "[custom js]" href) (execed))))
-            (util/p-handle
-             (fs/read-file (if (util/electron?) "" (config/get-repo-dir (state/get-current-repo))) href)
-             #(when-let [scripts (and % (string/trim %))]
-                (when-not (string/blank? scripts)
-                  (when (or (not should-ask?) (ask-allow))
-                    (try
-                      (js/eval scripts)
-                      (execed)
-                      (catch js/Error e
-                        (js/console.error "[custom js]" e)))))))))))))
+  (when-let [href (or
+                   (state/get-custom-js-link)
+                   (config/get-custom-js-path))]
+    (let [k (str "ls-js-allowed-" href)
+          execed #(swap! *js-execed conj href)
+          execed? (contains? @*js-execed href)
+          ask-allow #(let [r (js/confirm (t :plugin/custom-js-alert))]
+                       (if r
+                         (storage/set k (js/Date.now))
+                         (storage/set k false))
+                       r)
+          allowed! (storage/get k)
+          should-ask? (or (nil? allowed!)
+                          (> (- (js/Date.now) allowed!) 604800000))]
+      (when (and (not execed?)
+                 (not= false allowed!))
+        (if (string/starts-with? href "http")
+          (when (or (not should-ask?)
+                    (ask-allow))
+            (load href #(do (js/console.log "[custom js]" href) (execed))))
+          (util/p-handle
+           (fs/read-file (if (util/electron?) "" (config/get-repo-dir (state/get-current-repo))) href)
+           #(when-let [scripts (and % (string/trim %))]
+              (when-not (string/blank? scripts)
+                (when (or (not should-ask?) (ask-allow))
+                  (try
+                    (js/eval scripts)
+                    (execed)
+                    (catch js/Error e
+                      (js/console.error "[custom js]" e))))))))))))
 
 (defn toggle-wide-mode!
   []

+ 3 - 1
src/main/frontend/mobile/core.cljs

@@ -22,7 +22,7 @@
   []
   (let [path (fs/iOS-ensure-documents!)]
     (println "iOS container path: " path))
-
+  
   (.addEventListener js/window
                      "load"
                      (fn [_event]
@@ -30,6 +30,8 @@
                          (js/setTimeout #(deeplink/deeplink @*url)
                                         1000))))
 
+  (mobile-util/check-ios-zoomed-display)
+  
   (.removeAllListeners mobile-util/file-sync)
 
   (.addListener mobile-util/file-sync "debug"

+ 26 - 21
src/main/frontend/mobile/footer.cljs

@@ -6,15 +6,17 @@
             [frontend.state :as state]
             [frontend.ui :as ui]
             [frontend.util :as util]
-            [rum.core :as rum]))
+            [rum.core :as rum]
+            [frontend.components.svg :as svg]))
 
 (rum/defc mobile-bar-command [command-handler icon]
-  [:div
-   [:button.bottom-action
-    {:on-mouse-down (fn [e]
-                      (util/stop e)
-                      (command-handler))}
-    (ui/icon icon {:style {:fontSize ui/icon-size}})]])
+  [:button.bottom-action
+   {:on-mouse-down (fn [e]
+                     (util/stop e)
+                     (command-handler))}
+   (if (= icon "player-stop")
+     svg/circle-stop
+     (ui/icon icon {:style {:fontSize ui/icon-size}}))])
 
 (defn seconds->minutes:seconds
   [seconds]
@@ -35,19 +37,22 @@
   [state]
   (when (= (state/sub :editor/record-status) "RECORDING")
     (swap! *record-start inc))
-  [:div.flex.flex-row
-   (if (= (state/sub :editor/record-status) "NONE")
-     (do
-       (reset! *record-start -1)
-       (mobile-bar-command #(record/start-recording) "microphone"))
-     [:div.flex.flex-row
-      (mobile-bar-command #(record/stop-recording) "player-stop")
-      [:div.timer.pl-2 (seconds->minutes:seconds @*record-start)]])])
+  (if (= (state/sub :editor/record-status) "NONE")
+    (do
+      (reset! *record-start -1)
+      (mobile-bar-command record/start-recording "microphone"))
+    [:div.flex.flex-row.items-center
+     (mobile-bar-command record/stop-recording "player-stop")
+     [:div.timer.pl-2
+      {:on-click record/stop-recording}
+      (seconds->minutes:seconds @*record-start)]]))
 
 (rum/defc footer < rum/reactive
   []
-  (when (and (state/sub :mobile/show-tabbar?)
-             (state/get-current-repo))
+  (when (and
+         (state/mobile?)
+         (state/sub :mobile/show-tabbar?)
+         (state/get-current-repo))
     [:div.cp__footer.w-full.bottom-0.justify-between
      (audio-record-cp)
      (mobile-bar-command #(state/toggle-document-mode!) "notes")
@@ -55,8 +60,8 @@
       #(let [page (or (state/get-current-page)
                       (string/lower-case (date/journal-name)))]
          (editor-handler/api-insert-new-block!
-                    ""
-                    {:page page
-                     :edit-block? true
-                     :replace-empty-target? true}))
+          ""
+          {:page page
+           :edit-block? true
+           :replace-empty-target? true}))
       "edit")]))

+ 18 - 3
src/main/frontend/mobile/index.css

@@ -11,7 +11,7 @@
     height: 80px;
     /* border-top: 1.5px solid var(--ls-tertiary-border-color); */
     box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.10);
-    
+
     .ti, .timer {
         color: var(--ls-primary-text-color);
         opacity: 0.5;
@@ -51,12 +51,12 @@
           left: 0px;
           height: 40px;
       }
-      
+
       .show-submenu {
           display: block;
       }
   }
-  
+
   .toolbar-commands {
     justify-content: space-between;
     display: flex;
@@ -99,3 +99,18 @@ html.is-native-android {
     }
 }
 
+html.is-zoomed-native-ios {
+    .cp__footer {
+        height: 60px;
+    }
+
+    @media (orientation: landscape) {
+        .cp__footer {
+            height: 50px;
+        }
+    }
+}
+
+.bottom-action {
+    line-height: 1.15;
+}

+ 12 - 1
src/main/frontend/mobile/util.cljs

@@ -1,7 +1,8 @@
 (ns frontend.mobile.util
   (:require ["@capacitor/core" :refer [Capacitor registerPlugin]]
             ["@capacitor/splash-screen" :refer [SplashScreen]]
-            [clojure.string :as string]))
+            [clojure.string :as string]
+            [promesa.core :as p]))
 
 (defn platform []
   (.getPlatform Capacitor))
@@ -23,6 +24,7 @@
 (defonce folder-picker (registerPlugin "FolderPicker"))
 (when (native-ios?)
   (defonce download-icloud-files (registerPlugin "DownloadiCloudFiles"))
+  (defonce ios-utils (registerPlugin "Utils"))
   (defonce ios-file-container (registerPlugin "FileContainer"))
   (defonce file-sync (registerPlugin "FileSync")))
 
@@ -82,3 +84,12 @@
   []
   (when-let [model (get-idevice-model)]
     (string/starts-with? (first model) "iPad")))
+
+(defn check-ios-zoomed-display
+  "Detect whether iOS device is in Zoom Display"
+  []
+  (p/let [is-zoomed? (p/chain (.isZoomed ios-utils)
+                              #(js->clj % :keywordize-keys true))]
+    (when (:isZoomed is-zoomed?)
+      (let [^js cl (.-classList js/document.documentElement)]
+        (.add cl "is-zoomed-native-ios")))))

+ 5 - 2
src/main/frontend/modules/shortcut/before.cljs

@@ -1,6 +1,7 @@
 (ns frontend.modules.shortcut.before
   (:require [frontend.state :as state]
-            [frontend.util :as util]))
+            [frontend.util :as util]
+            [frontend.mobile.util :as mobile-util]))
 
 ;; before function
 (defn prevent-default-behavior
@@ -23,7 +24,9 @@
   [f]
   (fn [e]
     (when (state/editing?)
-      (util/stop e)
+      (if (mobile-util/native-ios?)
+        (util/stop-propagation e)
+        (util/stop e))
       (f e))))
 
 (defn enable-when-not-component-editing!

+ 8 - 3
src/main/frontend/state.cljs

@@ -58,7 +58,7 @@
      :modal/close-btn?                      nil
      :modal/subsets                         []
 
-     
+
      ;; right sidebar
      :ui/fullscreen?                        false
      :ui/settings-open?                     false
@@ -89,6 +89,7 @@
      :ui/shortcut-tooltip?                  (if (false? (storage/get :ui/shortcut-tooltip?))
                                               false
                                               true)
+     :ui/scrolling?                         false
      :document/mode?                        document-mode?
 
      :config                                {}
@@ -147,7 +148,7 @@
      :mobile/show-toolbar?                  false
      ;;; toolbar icon doesn't update correctly when clicking after separate it from box,
      ;;; add a random in (<= 1000000) to observer its update
-     :mobile/toolbar-update-observer        0 
+     :mobile/toolbar-update-observer        0
      :mobile/show-tabbar?                   false
 
      ;; plugin
@@ -1192,9 +1193,13 @@
     (set-state! :ui/shortcut-tooltip? (not mode))
     (storage/set :ui/shortcut-tooltip? (not mode))))
 
+(defn mobile?
+  []
+  (or (util/mobile?) (mobile-util/native-platform?)))
+
 (defn enable-tooltip?
   []
-  (if (or (util/mobile?) (mobile-util/native-platform?))
+  (if (mobile?)
     false
     (get (get (sub-config) (get-current-repo))
          :ui/enable-tooltip?

+ 44 - 42
src/main/frontend/ui.cljs

@@ -295,8 +295,8 @@
     (when-let [custom-theme (state/sub [:ui/custom-theme (keyword theme)])]
       (when-let [url (:url custom-theme)]
         (js/LSPluginCore.selectTheme (bean/->js custom-theme)
-                                     (bean/->js {:effect false :emit false}))
-        (state/set-state! :plugin/selected-theme (:url url))))))
+                                     (bean/->js {:emit false}))
+        (state/set-state! :plugin/selected-theme url)))))
 
 (defn setup-system-theme-effect!
   []
@@ -787,20 +787,31 @@
           :checked selected}]
         label])]))
 
-(rum/defcs tippy < rum/static
+(rum/defcs tippy < rum/reactive
   (rum/local false ::mounted?)
-  [state {:keys [fixed-position? open?] :as opts} child]
+  [state {:keys [fixed-position? open? in-editor?] :as opts} child]
   (let [*mounted? (::mounted? state)
-        mounted? @*mounted?
-        manual (not= open? nil)]
+        manual (not= open? nil)
+        edit-id (ffirst (state/sub :editor/editing?))
+        editing-node (when edit-id (gdom/getElement edit-id))
+        editing? (some? editing-node)
+        scrolling? (state/sub :ui/scrolling?)
+        open? (if manual open? @*mounted?)
+        disabled? (boolean
+                   (or
+                    (and in-editor?
+                         ;; editing in non-preview containers or scrolling
+                         (not (util/rec-get-tippy-container editing-node))
+                         (or editing? scrolling?))
+                    (not (state/enable-tooltip?))))]
     (Tippy (->
             (merge {:arrow true
                     :sticky true
                     :delay 600
                     :theme "customized"
-                    :disabled (not (state/enable-tooltip?))
+                    :disabled disabled?
                     :unmountHTMLWhenHide true
-                    :open (if manual open? @*mounted?)
+                    :open (if disabled? false open?)
                     :trigger (if manual "manual" "mouseenter focus")
                     ;; See https://github.com/tvkhoa/react-tippy/issues/13
                     :popperOptions {:modifiers {:flip {:enabled (not fixed-position?)}
@@ -809,18 +820,19 @@
                     :onShow #(reset! *mounted? true)
                     :onHide #(reset! *mounted? false)}
                    opts)
-            (assoc :html (if (or open? mounted?)
-                           (try
-                             (when-let [html (:html opts)]
-                               (if (fn? html)
-                                 (html)
-                                 [:div.px-2.py-1
-                                  html]))
-                             (catch js/Error e
-                               (log/error :exception e)
-                               [:div]))
-                           [:div {:key "tippy"} ""])))
-            (rum/fragment {:key "tippy-children"} child))))
+            (assoc :html (or
+                          (when open?
+                            (try
+                              (when-let [html (:html opts)]
+                                (if (fn? html)
+                                  (html)
+                                  [:div.px-2.py-1
+                                   html]))
+                              (catch js/Error e
+                                (log/error :exception e)
+                                [:div])))
+                          [:div {:key "tippy"} ""])))
+           (rum/fragment {:key "tippy-children"} child))))
 
 (defn slider
   [default-value {:keys [min max on-change]}]
@@ -868,7 +880,7 @@
 (rum/defc progress-bar
   [width]
   {:pre (integer? width)}
-  [:div.w-full.bg-indigo-200.rounded-full.h-2.5
+  [:div.w-full.bg-indigo-200.rounded-full.h-2.5.animate-pulse
    [:div.bg-indigo-600.h-2.5.rounded-full {:style {:width (str width "%")}
                                            :transition "width 1s"}]])
 
@@ -883,28 +895,18 @@
      label-right]]
    (progress-bar width)])
 
-(rum/defcs lazy-visible-inner <
+(rum/defcs lazy-visible-inner < rum/reactive
   {:init (fn [state]
            (assoc state
-                  ::ref (atom nil)
-                  ::height (atom 24)))
-   :did-mount (fn [state]
-                (when (last (:rum/args state))
-                  (let [observer (js/ResizeObserver. (fn [entries]
-                                                      (let [entry (first entries)
-                                                            *height (::height state)
-                                                            height' (.-height (.-contentRect entry))]
-                                                        (when (and (> height' @*height)
-                                                                   (not= height' 64))
-                                                          (reset! *height height')))))]
-                   (.observe observer @(::ref state))))
-                state)}
-  [state visible? content-fn _reset-height?]
-  [:div.lazy-visibility {:ref #(reset! (::ref state) %)
-                         :style {:min-height @(::height state)}}
+                  ::ref (atom nil)))}
+  [state visible? content-fn]
+  [:div.lazy-visibility
+   {:ref #(reset! (::ref state) %)
+    :style {:min-height 24}}
    (if visible?
-     (when (fn? content-fn) (content-fn))
-     [:div.shadow.rounded-md.p-4.w-full.mx-auto.fade-in.delay-1000.mb-5 {:style {:min-height 64}}
+     (when (fn? content-fn)
+       [:div.fade-in.faster-fade-in (content-fn)])
+     [:div.shadow.rounded-md.p-4.w-full.mx-auto.mb-5.fade-in {:style {:height 88}}
       [:div.animate-pulse.flex.space-x-4
        [:div.flex-1.space-y-3.py-1
         [:div.h-2.bg-base-4.rounded]
@@ -917,7 +919,7 @@
 (rum/defcs lazy-visible <
   (rum/local false ::visible?)
   (rum/local true ::active?)
-  [state content-fn sensor-opts {:keys [reset-height? once?]}]
+  [state content-fn sensor-opts {:keys [once?]}]
   (let [*active? (::active? state)]
     (if (or (util/mobile?) (mobile-util/native-platform?))
       (content-fn)
@@ -935,4 +937,4 @@
            :scrollThrottle 500
            :active @*active?}
           sensor-opts)
-         (lazy-visible-inner @*visible? content-fn reset-height?))))))
+         (lazy-visible-inner @*visible? content-fn))))))

+ 8 - 0
src/main/frontend/util.cljc

@@ -669,6 +669,14 @@
            :up
            :down)))))
 
+#?(:cljs
+   (defn rec-get-tippy-container
+     [node]
+     (if (and node (d/has-class? node "tippy-tooltip-content"))
+       node
+       (and node
+            (rec-get-tippy-container (gobj/get node "parentNode"))))))
+
 #?(:cljs
    (defn rec-get-blocks-container
      [node]

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

@@ -1,3 +1,3 @@
 (ns frontend.version)
 
-(defonce version "0.6.10")
+(defonce version "0.7.0")

+ 19 - 3
src/main/logseq/api.cljs

@@ -454,11 +454,27 @@
     (let [{:keys [before sibling isPageBlock properties]} (bean/->clj opts)
           page-name (and isPageBlock block-uuid-or-page-name)
           block-uuid (if isPageBlock nil (uuid block-uuid-or-page-name))
+          block-uuid' (if (and (not sibling) before block-uuid)
+                        (let [block (db/entity [:block/uuid block-uuid])
+                              first-child (db-model/get-by-parent-&-left (db/get-db)
+                                                                         (:db/id block)
+                                                                         (:db/id block))]
+                          (if first-child
+                            (:block/uuid first-child)
+                            block-uuid))
+                        block-uuid)
+          insert-at-first-child? (not= block-uuid' block-uuid)
+          [sibling? before?] (if insert-at-first-child?
+                               [true true]
+                               [sibling before])
+          before? (if (and (false? sibling?) before? (not insert-at-first-child?))
+                    false
+                    before?)
           new-block (editor-handler/api-insert-new-block!
                       content
-                      {:block-uuid block-uuid
-                       :sibling?   sibling
-                       :before?    before
+                      {:block-uuid block-uuid'
+                       :sibling?   sibling?
+                       :before?    before?
                        :page       page-name
                        :properties properties})]
       (bean/->js (normalize-keyword-for-json new-block)))))

+ 3 - 1
src/main/logseq/graph_parser/block.cljc

@@ -509,7 +509,9 @@
                 (seq (:properties-order properties))
                 (assoc :properties-order (:properties-order properties)))
         block (if (get-in block [:properties :collapsed])
-                (assoc block :collapsed? true)
+                (-> (assoc block :collapsed? true)
+                    (update :properties (fn [m] (dissoc m :collapsed)))
+                    (update :properties-order (fn [keys] (vec (remove #{:collapsed} keys)))))
                 block)
         block (assoc block
                      :content (get-block-content encoded-content block format pos-meta block-pattern))

+ 0 - 1
src/test/frontend/handler/repo_test.cljs

@@ -100,7 +100,6 @@
 
       (is (= {:title 98 :id 98
               :updated-at 47 :created-at 47
-              :collapsed 22
               :card-last-score 6 :card-repeats 6 :card-next-schedule 6
               :card-last-interval 6 :card-ease-factor 6 :card-last-reviewed 6
               :alias 6}

+ 3 - 3
src/test/frontend/modules/outliner/core_test.cljs

@@ -390,7 +390,7 @@
               (recur (conj result next) next)))
           result)))))
 
-(deftest ^:long random-inserts
+#_(deftest ^:long random-inserts
   (testing "Random inserts"
     (transact-random-tree!)
     (let [c1 (get-blocks-count)
@@ -402,7 +402,7 @@
       (let [total (get-blocks-count)]
         (is (= total (+ c1 @*random-count)))))))
 
-(deftest ^:long random-deletes
+#_(deftest ^:long random-deletes
   (testing "Random deletes"
     (transact-random-tree!)
     (dotimes [_i 100]
@@ -412,7 +412,7 @@
           (outliner-tx/transact! {:graph test-db}
             (outliner-core/delete-blocks! blocks {})))))))
 
-(deftest ^:long random-moves
+#_(deftest ^:long random-moves
   (testing "Random moves"
     (transact-random-tree!)
     (let [c1 (get-blocks-count)

+ 14 - 0
templates/dummy-notes-it.md

@@ -0,0 +1,14 @@
+---
+title: Come prendere appunti fittizi?
+---
+
+- Ciao, io sono un blocco!
+:PROPERTIES:
+:id: 5f713e91-8a3c-4b04-a33a-c39482428e2d
+:END:
+    - Io sono un blocco figlio!
+    - Io sono un altro blocco figlio!
+- Hey, io sono un altro blocco!
+:PROPERTIES:
+:id: 5f713ea8-8cba-403d-ac00-9964b1ec7190
+:END:

+ 27 - 0
templates/tutorial-it.md

@@ -0,0 +1,27 @@
+## Ciao, benvenuto su Logseq
+- Logseq è una piattaforma con la _privacy come priorità_, [open-source](https://github.com/logseq/logseq) per la gestione della _conoscenza_ e la collaborazione.
+- Questo è un tutorial di 3 minuti su come utilizzare Logseq. Iniziamo!
+- Ecco alcuni suggerimenti che potrebbero essere utili.
+#+BEGIN_TIP
+Fare clic per modificare qualsiasi blocco.
+Digita "Invio" per creare un nuovo blocco.
+Digita `Maiusc+Invio` per creare una nuova riga.
+Digita `/` per mostrare tutti i comandi.
+#+END_TIP
+- 1. Creiamo una pagina chiamata [[Come prendere appunti fittizi?]]. Puoi fare clic su di esso per andare a quella pagina, oppure puoi "Maiusc + clic" per aprirlo nella barra laterale destra! Ora dovresti vedere sia _Riferimenti collegati_ che _Riferimenti non collegati_.
+- 2. Facciamo riferimento ad alcuni blocchi su [[Come prendere appunti fittizi?]], puoi fare `Maiusc+Clic` su qualsiasi riferimento di blocco per aprirlo nella barra laterale destra. Prova a fare
+alcune modifiche sulla barra laterale destra, verranno modificati anche quei blocchi di riferimento!
+    - ((5f713e91-8a3c-4b04-a33a-c39482428e2d)) : This is a block reference.
+    - ((5f713ea8-8cba-403d-ac00-9964b1ec7190)) : This is another block reference.
+- 3. Supportate i tag?
+    - Naturalmente, questo è un tag #falso.
+- 4. Supportate le azioni come todo/doing/done e le priorità?
+    - Si, digita `/` e scegli la tua parola chiave todo o la tua priorità preferita (A/B/C).
+    - NOW [#A] Un tutorial fittizio su "Come prendere appunti fittizi?"
+    - LATER [#A] Guarda questo fantastico video di [:a {:href "https://twitter.com/shuomi3" :target "_blank"} "@shuomi3"] su come usare Logseq per prendere appunti e organizzare la tua vita!
+    {{youtube <https://www.youtube.com/watch?v=BhHfF0P9A80&ab_channel=ShuOmi>}}
+
+    - DONE Crea una pagina
+    - CANCELED [#C] Scrivi una pagina con più di 1000 blocchi
+- Questo è tutto! Puoi creare più blocchi o aprire una directory locale per importare alcune note adesso!
+- Puoi anche scaricare la nostra app desktop su <https://github.com/logseq/logseq/releases>

Some files were not shown because too many files changed in this diff