From 1ef089b3eb7dc05ae15cb2cbd9e401785b57b15e Mon Sep 17 00:00:00 2001 From: charlie Date: Thu, 22 May 2025 17:58:00 +0800 Subject: [PATCH] enhance(capacitor): direction keys management for the block editor --- src/main/capacitor/components/blocks.cljs | 34 +++++++++++++++++++++++ src/main/capacitor/components/editor.cljs | 21 ++++++++++---- src/main/capacitor/externals.js | 16 +++++++++++ 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/main/capacitor/components/blocks.cljs b/src/main/capacitor/components/blocks.cljs index 473bc1e588..d0d6333d3a 100644 --- a/src/main/capacitor/components/blocks.cljs +++ b/src/main/capacitor/components/blocks.cljs @@ -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))] diff --git a/src/main/capacitor/components/editor.cljs b/src/main/capacitor/components/editor.cljs index dc48aeb536..28aed98cc0 100644 --- a/src/main/capacitor/components/editor.cljs +++ b/src/main/capacitor/components/editor.cljs @@ -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! diff --git a/src/main/capacitor/externals.js b/src/main/capacitor/externals.js index aaae43631d..0133eca743 100644 --- a/src/main/capacitor/externals.js +++ b/src/main/capacitor/externals.js @@ -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, }