enhance: way better cursor restore for undo/redo

This commits records both the start pos (user starts to type) and end
pos (before transaction), because the user always wants undo to move
the cursor back to the start position and redo to the end position.
pull/10839/head
Tienson Qin 2024-01-10 00:27:21 +08:00
parent 324ed9a9cd
commit 9663d1bad1
5 changed files with 17 additions and 40 deletions

View File

@ -2917,6 +2917,10 @@
hashtag? (or (surround-by? input "#" " ")
(surround-by? input "#" :end)
(= key "#"))]
(when (and (not @(:editor/start-pos @state/state))
(not (and key (string/starts-with? key "Arrow"))))
(state/set-state! :editor/start-pos pos))
(cond
(and (contains? #{"ArrowLeft" "ArrowRight"} key)
(contains? #{:property-search :property-value-search} (state/get-editor-action)))

View File

@ -8,13 +8,13 @@
[goog.dom :as gdom]))
(defn restore-cursor!
[{:keys [last-edit-block container pos]}]
[{:keys [last-edit-block container pos end-pos]} undo?]
(when (and container last-edit-block)
#_:clj-kondo/ignore
(when-let [container (gdom/getElement container)]
(when-let [block-uuid (:block/uuid last-edit-block)]
(when-let [block (db/pull [:block/uuid block-uuid])]
(editor/edit-block! block pos
(editor/edit-block! block (if undo? pos end-pos)
(:block/uuid block)
{:custom-content (:block/content block)}))))))

View File

@ -133,41 +133,13 @@
(pop-undo))
(pop-undo)))
(defn- get-next-tx-editor-cursor
[tx-id]
(let [result (->> (sort (keys @(:history/tx->editor-cursor @state/state)))
(split-with #(not= % tx-id))
second)]
(when (> (count result) 1)
(when-let [next-tx-id (nth result 1)]
(get @(get @state/state :history/tx->editor-cursor) next-tx-id)))))
(defn- get-previous-tx-id
[tx-id]
(let [result (->> (sort (keys @(:history/tx->editor-cursor @state/state)))
(split-with #(not= % tx-id))
first)]
(when (>= (count result) 1)
(last result))))
(defn- get-previous-tx-editor-cursor
[tx-id]
(when-let [prev-tx-id (get-previous-tx-id tx-id)]
(get @(get @state/state :history/tx->editor-cursor) prev-tx-id)))
(defn undo
[]
(when-let [e (smart-pop-undo)]
(let [{:keys [txs tx-meta tx-id]} e
new-txs (get-txs false txs)
current-editor-cursor (get @(get @state/state :history/tx->editor-cursor) tx-id)
save-block? (= (:outliner-op tx-meta) :save-block)
prev-editor-cursor (get-previous-tx-editor-cursor tx-id)
editor-cursor (if (and save-block?
(= (:block/uuid (:last-edit-block prev-editor-cursor))
(:block/uuid (state/get-edit-block))))
prev-editor-cursor
current-editor-cursor)]
editor-cursor current-editor-cursor]
(push-redo e)
(transact! new-txs (merge {:undo? true}
tx-meta))
@ -181,10 +153,7 @@
[]
(when-let [{:keys [txs tx-meta tx-id] :as e} (smart-pop-redo)]
(let [new-txs (get-txs true txs)
current-editor-cursor (get @(get @state/state :history/tx->editor-cursor) tx-id)
editor-cursor (if (= (:outliner-op tx-meta) :save-block)
current-editor-cursor
(get-next-tx-editor-cursor tx-id))]
current-editor-cursor (get @(get @state/state :history/tx->editor-cursor) tx-id)]
(push-undo e)
(transact! new-txs (merge {:redo? true}
tx-meta))
@ -192,7 +161,7 @@
(state/pub-event! [:whiteboard/redo e]))
(assoc e
:txs-op new-txs
:editor-cursor editor-cursor))))
:editor-cursor current-editor-cursor))))
(defn toggle-undo-redo-mode!
[]

View File

@ -56,8 +56,8 @@
(fn [m] (assoc m tx-id editor-cursor)))))
(defn restore-cursor-and-app-state!
[{:keys [editor-cursor app-state]}]
(history/restore-cursor! editor-cursor)
[{:keys [editor-cursor app-state]} undo?]
(history/restore-cursor! editor-cursor undo?)
(history/restore-app-state! app-state))
(defn invoke-hooks
@ -101,9 +101,11 @@
(when-let [state (:ui/restore-cursor-state @state/state)]
(when (or undo? redo?)
(restore-cursor-and-app-state! state)
(restore-cursor-and-app-state! state undo?)
(state/set-state! :ui/restore-cursor-state nil)))
(state/set-state! :editor/start-pos nil)
(when (and state/lsp-enabled?
(seq blocks)
(<= (count blocks) 1000))

View File

@ -117,6 +117,7 @@
:config {}
:block/component-editing-mode? false
:editor/start-pos (atom nil)
:editor/op (atom nil)
:editor/latest-op (atom nil)
:editor/hidden-editors #{} ;; page names
@ -1260,7 +1261,8 @@ Similar to re-frame subscriptions"
(when container
{:last-edit-block edit-block
:container (gobj/get container "id")
:pos (or (cursor/pos (gdom/getElement edit-input-id))
:pos @(:editor/start-pos @state)
:end-pos (or (cursor/pos (gdom/getElement edit-input-id))
(count (:block/content edit-block)))})))
(defn clear-edit!