浏览代码

enhance(capacitor): improve block editor

charlie 5 月之前
父节点
当前提交
05ca8fd883

+ 1 - 1
src/main/capacitor/app.cljs

@@ -212,7 +212,7 @@
               (fn []
                 (cond
                   (not (nil? (state/get-editing-block)))
-                  (state/set-editing-block! nil)
+                  (state/exit-editing!)
 
                   :else
                   (cc-utils/nav-pop!)))

+ 42 - 32
src/main/capacitor/components/blocks.cljs

@@ -2,6 +2,7 @@
   (:require [capacitor.state :as state]
             [clojure.string :as string]
             [frontend.db.model :as db-model]
+            [frontend.util.cursor :as cursor]
             [promesa.core :as p]
             [rum.core :as rum]
             [frontend.db.async :as db-async]
@@ -96,43 +97,49 @@
 (rum/defc block-editor
   [block]
   (let [content (:block/title block)
-        exit! #(state/set-state! :editing-block nil)]
+        block-uuid (:block/uuid block)
+        current-repo (fstate/get-current-repo)]
+
     (cc-editor/editor-aux content
-      {:on-outside!
+      {:on-focused!
+       (fn [^js input]
+         (let [cursor-at (some-> (state/get-editing-opts) :cursor-at)]
+           (if (number? cursor-at)
+             (cursor/move-cursor-to input cursor-at)
+             (cursor/move-cursor-to-end input))))
+
+       :on-outside!
        (fn [^js e]
          (let [edit-target? (some-> e (.-target) (cc-common/get-dom-block-uuid))]
            (when edit-target?
              (cc-common/keep-keyboard-open e))
            (when (and (not edit-target?)
                    (= block (:editing-block @state/*state)))
-             (exit!))))
+             (state/exit-editing!))))
 
        :on-save!
-       (fn [content {:keys [enter?]}]
-         (let [block-uuid (:block/uuid block)
-               current-repo (fstate/get-current-repo)]
-
-           ;; update block content
-           (-> (do (when enter? (exit!))
-                 ;; check block exist?
-                 (when-not (db-utils/entity (:db/id block))
-                   (throw nil))
-                 (editor-handler/save-block! current-repo block-uuid content))
-             (p/then (fn []
-                       (state/set-state! [:modified-blocks block-uuid] (js/Date.now))
-                       (when enter?
-                         ;; create new block
-                         (cc-common/keep-keyboard-open nil)
-                         (-> (insert-new-block! "" {:block-uuid block-uuid})
-                           (p/then (fn [new-block]
-                                     (prn :debug "new block:" new-block)
-                                     (when-let [parent-block (:block/parent new-block)]
-                                       (state/set-state! [:modified-pages (:block/uuid parent-block)] (js/Date.now)))
-                                     ;; edit the new block
-                                     (js/requestAnimationFrame #(state/set-editing-block! new-block))
-                                     )))
-                         )))
-             (p/catch #(notification/show! (str %) :error)))))
+       (fn [content {:keys [enter? esc?]}]
+         ;; update block content
+         (-> (do (when (or enter? esc?) (state/exit-editing!))
+               ;; check block exist?
+               (when-not (db-utils/entity (:db/id block))
+                 (throw nil))
+               (editor-handler/save-block! current-repo block-uuid content))
+           (p/then (fn []
+                     (state/set-state! [:modified-blocks block-uuid] (js/Date.now))
+                     (when enter?
+                       ;; create new block
+                       (cc-common/keep-keyboard-open nil)
+                       (-> (insert-new-block! "" {:block-uuid block-uuid})
+                         (p/then (fn [new-block]
+                                   (prn :debug "new block:" new-block)
+                                   (when-let [parent-block (:block/parent new-block)]
+                                     (state/set-state! [:modified-pages (:block/uuid parent-block)] (js/Date.now)))
+                                   ;; edit the new block
+                                   (js/requestAnimationFrame #(state/edit-block! new-block))
+                                   )))
+                       )))
+           (p/catch #(notification/show! (str %) :error))))
 
        :on-delete!
        (fn [content]
@@ -140,18 +147,21 @@
                parent-block (:block/parent block)]
            (cond
              (and (nil? prev-block) (nil? parent-block)) nil
+
              :else
              (let [has-children? (seq (:block/_parent block))]
                (when-not has-children?
                  (p/do!
                    (editor-handler/delete-block-aux! block)
                    (state/set-state! [:modified-blocks (:block/uuid block)] (js/Date.now))
+                   (when (and (false? (some-> content (string/trim) (string/blank?))) prev-block)
+                     (editor-handler/save-block! current-repo prev-block
+                       (str (:block/title prev-block) content)))
                    (when prev-block
                      (cc-common/keep-keyboard-open nil)
-                     (js/requestAnimationFrame #(state/set-editing-block! prev-block)))
-                   (when (false? (some-> content (string/trim) (string/blank?)))
-                     (notification/show! "concat prev block content!!")
-                     )))))
+                     (state/set-state! [:modified-blocks (:block/uuid prev-block)] (js/Date.now))
+                     (js/requestAnimationFrame #(state/edit-block! prev-block
+                                                  {:cursor-at (count (:block/title prev-block))})))))))
            (prn :debug "delete node:" (:db/id block) (:block/title prev-block))
            ))
        })))

+ 19 - 13
src/main/capacitor/components/editor.cljs

@@ -7,7 +7,7 @@
             [frontend.handler.notification :as notification]))
 
 (rum/defc editor-aux
-  [content {:keys [on-outside! on-save! on-delete!]}]
+  [content {:keys [on-outside! on-save! on-delete! on-focused! on-keydown! on-keyup!]}]
 
   (let [*input (rum/use-ref nil)]
 
@@ -17,8 +17,8 @@
           (fn []
             (when-let [^js input (some-> (rum/deref *input))]
               (.focus input)
-              (let [len (.-length (.-value input))]
-                (.setSelectionRange input len len))
+              (when on-focused!
+                (on-focused! input))
               ;(.scrollIntoView input #js {:behavior "smooth", :block "start"})
               )))
         #())
@@ -35,7 +35,7 @@
 
     (let [save-handle!
           (fn [opts]
-            (let [content (.-value (rum/deref *input))]
+            (when-let [content (some-> (rum/deref *input) (.-value))]
               (when on-save!
                 (prn :debug "save block content:" content opts)
                 (on-save! content opts))))
@@ -52,19 +52,25 @@
                         (let [ekey (.-key e)
                               target (.-target e)
                               enter? (= ekey "Enter")
+                              esc? (= ekey "Escape")
                               backspace? (= ekey "Backspace")]
 
-                          (cond
-                            (and enter? (cursor/end? target))
-                            (do (save-handle! {:enter? true})
-                              (util/stop e))
+                          (when (or (nil? on-keydown!)
+                                  (not (false? (on-keydown! e))))
+                            (cond
+                              (or (and enter? (cursor/end? target)) esc?)
+                              (do (save-handle! {:enter? enter? :esc? esc?})
+                                (util/stop e))
 
-                            (and backspace? (cursor/start? target))
-                            (do (delete-handle! {})
-                              (util/stop e))
+                              (and backspace? (cursor/start? target))
+                              (do (delete-handle! {})
+                                (util/stop e))
 
-                            :else (debounce-save-handle!)
-                            )))
+                              :else (debounce-save-handle!)
+                              ))))
+         :on-key-up (fn [^js e]
+                      (when on-keyup!
+                        (on-keyup! e)))
          :default-value content}))))
 
 (rum/defc content-aux

+ 13 - 3
src/main/capacitor/state.cljs

@@ -6,8 +6,9 @@
 (defonce *state
   (atom {:version 0
          :editing-block nil
+         :editing-opts nil
          :modified-pages {}
-         :modified-blocks {} ;; {:uuid timestamp}
+         :modified-blocks {}                                ;; {:uuid timestamp}
          }))
 
 (defn use-nav-root [] (r/use-atom *nav-root))
@@ -50,5 +51,14 @@
 (defn get-editing-block []
   (:editing-block @*state))
 
-(defn set-editing-block! [block]
-  (set-state! :editing-block block))
+(defn edit-block!
+  ([block] (edit-block! block nil))
+  ([block opts]
+   (set-state! :editing-block block)
+   (set-state! :editing-opts opts)))
+
+(defn exit-editing! []
+  (edit-block! nil nil))
+
+(defn get-editing-opts []
+  (:editing-opts @*state))