mirror of
https://github.com/logseq/logseq.git
synced 2026-05-24 20:54:09 +00:00
enhance(capacitor): direction keys management for the block editor
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
[clojure.string :as string]
|
||||
[frontend.db.model :as db-model]
|
||||
[frontend.util.cursor :as cursor]
|
||||
[dommy.core :as dom]
|
||||
[promesa.core :as p]
|
||||
[rum.core :as rum]
|
||||
[frontend.db.async :as db-async]
|
||||
@@ -93,6 +94,29 @@
|
||||
opts {:edit-block? false})]
|
||||
(editor-handler/api-insert-new-block! content opts')))
|
||||
|
||||
(defn dom-prev-block
|
||||
[^js current-block-node]
|
||||
(when-let [prev-node (loop [node current-block-node]
|
||||
(when-let [node (some-> node (.-previousSibling))]
|
||||
(when node
|
||||
(if (dom/has-class? node "block-item")
|
||||
node
|
||||
(recur node)))))]
|
||||
(let [uuid' (.-blockid (.-dataset prev-node))]
|
||||
(db-model/get-block-by-uuid (uuid uuid')))))
|
||||
|
||||
(defn dom-next-block
|
||||
[^js current-block-node]
|
||||
(when-let [next-node (loop [node current-block-node]
|
||||
(when-let [node (some-> node (.-nextSibling))]
|
||||
(when node
|
||||
(if (dom/has-class? node "block-item")
|
||||
node
|
||||
(recur node)))))]
|
||||
(prn :debug next-node)
|
||||
(let [uuid' (.-blockid (.-dataset next-node))]
|
||||
(db-model/get-block-by-uuid (uuid uuid')))))
|
||||
|
||||
;; components
|
||||
(rum/defc block-editor
|
||||
[block]
|
||||
@@ -108,6 +132,16 @@
|
||||
(cursor/move-cursor-to input cursor-at)
|
||||
(cursor/move-cursor-to-end input))))
|
||||
|
||||
:on-bounded!
|
||||
(fn [dir ^js input]
|
||||
(case dir
|
||||
:up (when-let [prev-block (dom-prev-block (.closest input ".block-item"))]
|
||||
(state/edit-block! prev-block {}))
|
||||
:down (when-let [next-block (dom-next-block (.closest input ".block-item"))]
|
||||
(js/console.log next-block)
|
||||
(state/edit-block! next-block {}))
|
||||
:dune))
|
||||
|
||||
:on-outside!
|
||||
(fn [^js e]
|
||||
(let [edit-target? (some-> e (.-target) (cc-common/get-dom-block-uuid))]
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
(ns capacitor.components.editor
|
||||
(:require [rum.core :as rum]
|
||||
[capacitor.components.ui :as ui]
|
||||
[cljs-bean.core :as bean]
|
||||
[capacitor.ionic :as ionic]
|
||||
[frontend.util.cursor :as cursor]
|
||||
[frontend.util :as util]
|
||||
[frontend.handler.notification :as notification]))
|
||||
|
||||
(rum/defc editor-aux
|
||||
[content {:keys [on-outside! on-save! on-delete! on-focused! on-keydown! on-keyup!]}]
|
||||
[content {:keys [on-outside! on-save! on-delete! on-focused! on-keydown! on-keyup! on-bounded!]}]
|
||||
|
||||
(let [*input (rum/use-ref nil)]
|
||||
|
||||
@@ -48,25 +49,35 @@
|
||||
(ui/textarea
|
||||
{:class "editor-aux-input bg-gray-200 border-none"
|
||||
:ref *input
|
||||
:on-change (fn [] (debounce-save-handle!))
|
||||
:on-key-down (fn [^js e]
|
||||
(let [ekey (.-key e)
|
||||
target (.-target e)
|
||||
enter? (= ekey "Enter")
|
||||
esc? (= ekey "Escape")
|
||||
backspace? (= ekey "Backspace")]
|
||||
backspace? (= ekey "Backspace")
|
||||
arrow-up? (= ekey "ArrowUp")
|
||||
arrow-down? (= ekey "ArrowDown")]
|
||||
|
||||
(when (or (nil? on-keydown!)
|
||||
(not (false? (on-keydown! e))))
|
||||
(cond
|
||||
(or arrow-up? arrow-down?)
|
||||
(when-let [{:keys [isFirstLine isLastLine]} (some-> (.checkCursorLine js/window.externalsjs target) (bean/->clj))]
|
||||
(when (and on-bounded! (or (and arrow-up? isFirstLine)
|
||||
(and arrow-down? isLastLine)))
|
||||
(on-bounded! (if arrow-up? :up :down) target)
|
||||
(util/stop e)))
|
||||
|
||||
(or (and enter? (cursor/end? target)) esc?)
|
||||
(do (save-handle! {:enter? enter? :esc? esc?})
|
||||
(util/stop e))
|
||||
|
||||
(and backspace? (cursor/start? target))
|
||||
(and backspace?
|
||||
(cursor/start? target)
|
||||
(not (util/input-text-selected? target)))
|
||||
(do (delete-handle! {})
|
||||
(util/stop e))
|
||||
|
||||
:else (debounce-save-handle!)
|
||||
))))
|
||||
:on-key-up (fn [^js e]
|
||||
(when on-keyup!
|
||||
|
||||
@@ -55,7 +55,23 @@ const settleStatusBar = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
function checkCursorLine (textarea) {
|
||||
const { value, selectionStart } = textarea
|
||||
|
||||
const lines = value.split('\n')
|
||||
const totalLines = lines.length
|
||||
|
||||
const textBeforeCursor = value.substring(0, selectionStart)
|
||||
const currentLine = textBeforeCursor.split('\n').length
|
||||
|
||||
const isFirstLine = currentLine === 1
|
||||
const isLastLine = currentLine === totalLines
|
||||
|
||||
return { isFirstLine, isLastLine, currentLine, totalLines }
|
||||
}
|
||||
|
||||
window.externalsjs = {
|
||||
initGlobalListeners,
|
||||
settleStatusBar,
|
||||
checkCursorLine,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user