Browse Source

enhance(toggle): fix `t o` doesn't collapse all blocks && add `Exppand all` and `Collapse all` menu item for toggling block && auto expand children of the top block if collapse(fix #3222) && basic support for toggling by clicking the left bar of the block (see https://discuss.logseq.com/t/collapse-all-child-bullets-by-clicking-the-alignment-line/1937/3)

shidenggui 4 years ago
parent
commit
9e117d2618

+ 17 - 6
src/main/frontend/components/block.cljs

@@ -1336,6 +1336,8 @@
 
 
 (defn- bullet-on-click
 (defn- bullet-on-click
   [e block uuid]
   [e block uuid]
+  (if (-> block :block/properties :collapsed)
+    (editor-handler/expand-all! uuid (:block/level block)))
   (if (gobj/get e "shiftKey")
   (if (gobj/get e "shiftKey")
     (do
     (do
       (state/sidebar-add-block!
       (state/sidebar-add-block!
@@ -1346,6 +1348,14 @@
       (util/stop e))
       (util/stop e))
     (route-handler/redirect-to-page! uuid)))
     (route-handler/redirect-to-page! uuid)))
 
 
+(defn- block-left-border-on-click
+  [e children]
+  (if (< (.-offsetX (.-nativeEvent e)) 10)
+    (let [block-ids (map :block/uuid children)]
+      (if (some editor-handler/collapsable? block-ids)
+        (dorun (map editor-handler/collapse-block! block-ids))
+        (dorun (map editor-handler/expand-block! block-ids))))))
+
 (rum/defc block-children < rum/reactive
 (rum/defc block-children < rum/reactive
   [config children collapsed? *ref-collapsed?]
   [config children collapsed? *ref-collapsed?]
   (let [ref? (:ref? config)
   (let [ref? (:ref? config)
@@ -1355,12 +1365,13 @@
                (seq children)
                (seq children)
                (not collapsed?))
                (not collapsed?))
       (let [doc-mode? (state/sub :document/mode?)]
       (let [doc-mode? (state/sub :document/mode?)]
-        [:div.block-children {:style {:margin-left (if doc-mode? 18
-                                                       (if (or (mobile-util/native-android?)
-                                                               (mobile-util/native-iphone?))
-                                                         22
-                                                         29))
-                                      :display (if collapsed? "none" "")}}
+        [:div.block-children {:style    {:margin-left (if doc-mode? 18
+                                                                    (if (or (mobile-util/native-android?)
+                                                                            (mobile-util/native-iphone?))
+                                                                      22
+                                                                      29))
+                                         :display     (if collapsed? "none" "")}
+                              :on-click (fn [event] (block-left-border-on-click event children))}
          (for [child children]
          (for [child children]
            (when (map? child)
            (when (map? child)
              (let [child (dissoc child :block/meta)
              (let [child (dissoc child :block/meta)

+ 12 - 0
src/main/frontend/components/content.cljs

@@ -234,6 +234,18 @@
                           (editor-handler/cut-block! block-id))}
                           (editor-handler/cut-block! block-id))}
              "Cut")
              "Cut")
 
 
+            (ui/menu-link
+              {:key      "Expand all"
+               :on-click (fn [_e]
+                           (editor-handler/expand-all! block-id))}
+              "Expand all")
+
+            (ui/menu-link
+              {:key      "Collapse all"
+               :on-click (fn [_e]
+                           (editor-handler/collapse-all! block-id))}
+              "Collapse all")
+
             (when (state/sub [:plugin/simple-commands])
             (when (state/sub [:plugin/simple-commands])
               (when-let [cmds (state/get-plugins-commands-with-type :block-context-menu-item)]
               (when-let [cmds (state/get-plugins-commands-with-type :block-context-menu-item)]
                 (for [[_ {:keys [key label] :as cmd} action pid] cmds]
                 (for [[_ {:keys [key label] :as cmd} action pid] cmds]

+ 48 - 27
src/main/frontend/handler/editor.cljs

@@ -3305,8 +3305,20 @@
     (util/forward-kill-word input)
     (util/forward-kill-word input)
     (state/set-edit-content! (state/get-edit-input-id) (.-value input))))
     (state/set-edit-content! (state/get-edit-input-id) (.-value input))))
 
 
+(defn collapsable? [block-id]
+  (if-let [block (db-model/query-block-by-uuid block-id)]
+    (let [block (block/parse-title-and-body block)]
+      (and
+        (nil? (-> block :block/properties :collapsed))
+        (or (not-empty (:block/body block))
+            (db-model/has-children? block-id))))
+    false))
+
 (defn all-blocks-with-level
 (defn all-blocks-with-level
   "Return all blocks associated with correct level
   "Return all blocks associated with correct level
+   if :root-block is not nil, only return root block with its children
+   if :max-level is not nil, only return blocks that level <= :max-level
+   if :expanded? true, return expanded children
    if :collapse? true, return without any collapsed children
    if :collapse? true, return without any collapsed children
    for example:
    for example:
    - a
    - a
@@ -3319,7 +3331,7 @@
     [{:block a :level 1}
     [{:block a :level 1}
      {:block b :level 2}
      {:block b :level 2}
      {:block e :level 2}]"
      {:block e :level 2}]"
-  [{:keys [collapse?] :or {collapse? false}}]
+  [{:keys [collapse? expanded? root-block max-level] :or {collapse? false expanded? false root-block nil max-level nil}}]
   (when-let [page (or (state/get-current-page)
   (when-let [page (or (state/get-current-page)
                       (date/today))]
                       (date/today))]
     (->>
     (->>
@@ -3327,24 +3339,27 @@
          (db/get-page-blocks-no-cache)
          (db/get-page-blocks-no-cache)
          (tree/blocks->vec-tree page))
          (tree/blocks->vec-tree page))
 
 
-     (#(if collapse?
-         (w/postwalk
-          (fn [x]
-            (if (and (map? x) (-> x :block/properties :collapsed))
-              (assoc x :block/children []) x)) %) %))
+     (#(cond->> %
+         root-block (map (fn find [root]
+                       (if (= root-block (:block/uuid root))
+                         root
+                         (first (filter find (:block/children root []))))))))
+
+     (#(cond->> %
+         collapse? (w/postwalk
+                     (fn [x]
+                      (if (and (map? x) (-> x :block/properties :collapsed))
+                        (assoc x :block/children []) x)))))
 
 
      (mapcat (fn [x] (tree-seq map? :block/children x)))
      (mapcat (fn [x] (tree-seq map? :block/children x)))
 
 
-     (map (fn [x] (dissoc x :block/children))))))
+     (#(cond->> %
+         expanded? (filter (fn [b] (collapsable? (:block/uuid b))))))
 
 
-(defn collapsable? [block-id]
-  (if-let [block (db-model/query-block-by-uuid block-id)]
-    (let [block (block/parse-title-and-body block)]
-      (and
-       (nil? (-> block :block/properties :collapsed))
-       (or (not-empty (:block/body block))
-           (db-model/has-children? block-id))))
-    false))
+     (#(cond->> %
+         max-level (filter (fn [b] (>= max-level (:block/level b))))))
+
+     (map (fn [x] (dissoc x :block/children))))))
 
 
 (defn collapse-block! [block-id]
 (defn collapse-block! [block-id]
   (when (collapsable? block-id)
   (when (collapsable? block-id)
@@ -3425,20 +3440,26 @@
                  (collapse-block! uuid))))))))))
                  (collapse-block! uuid))))))))))
 
 
 (defn- collapse-all!
 (defn- collapse-all!
-  []
-  (let [blocks-to-collapse
-        (->> (all-blocks-with-level {:collapse? true})
-             (filter (fn [b] (collapsable? (:block/uuid b)))))]
-    (when (seq blocks-to-collapse)
-      (doseq [{:block/keys [uuid]} blocks-to-collapse]
-        (collapse-block! uuid)))))
+  ([]
+   (collapse-all! nil))
+  ([block-id]
+   (collapse-all! block-id nil))
+  ([block-id max-level]
+   (let [blocks-to-collapse (all-blocks-with-level {:expanded? true :root-block block-id :max-level max-level})]
+     (when (seq blocks-to-collapse)
+       (doseq [{:block/keys [uuid]} blocks-to-collapse]
+         (collapse-block! uuid))))))
 
 
 (defn- expand-all!
 (defn- expand-all!
-  []
-  (->> (all-blocks-with-level {})
-       (filter (fn [b] (-> b :block/properties :collapsed)))
-       (map (comp expand-block! :block/uuid))
-       doall))
+  ([]
+   (expand-all! nil))
+  ([block-id]
+   (expand-all! block-id nil))
+  ([block-id max-level]
+   (->> (all-blocks-with-level {:root-block block-id :max-level max-level})
+        (filter (fn [b] (-> b :block/properties :collapsed)))
+        (map (comp expand-block! :block/uuid))
+        doall)))
 
 
 (defn toggle-open! []
 (defn toggle-open! []
   (let [all-collapsed?
   (let [all-collapsed?