enhance(capacitor): improve block editor

This commit is contained in:
charlie
2025-05-22 15:06:47 +08:00
parent ede7c8f01e
commit 05ca8fd883
4 changed files with 75 additions and 49 deletions

View File

@@ -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!)))

View File

@@ -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))
))
})))

View File

@@ -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

View File

@@ -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))